# coding=utf-8
import json
import traceback
from django.utils import timezone
from rest_framework.decorators import action
from django.db import transaction
from django.db.models import  F
from utils.custom_modelviewset import CustomModelViewSet
from utils import response_ok, response_error
from utils.permission import IsStaff
from apps.examination.exam.serializers import *
from apps.examination.exam.filters import *
from apps.system.models import SysLog

from apps.examination.exam.models import ExamAnswerLog, ExamAnswerOptionLog, ExamAnswerFillLog
from apps.examination.exampaper.models import ExamPaperDetail, ExamQuestion
from apps.examination.examquestion.models import ExamQuestionOption, ExamQuestionFill, ExamQuestionFeedback
from apps.examination.examquestion.serializers import ExamQuestionFeedbackSerializer
from apps.practise.errorbook.models import ErrorBook
from utils.format import strftime

class ExamLogViewSet(CustomModelViewSet):
    permission_classes = [IsStaff, ]
    queryset = ExamLog.objects.filter(delete=False, type=ExamLog.FORMAL,)
    serializer_class = StaffExamLogSerializer

    def filter_queryset(self, queryset):
        queryset = queryset.filter(user=self.request.user)
        return queryset

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = StaffExamLogRetrieveSerializer(instance)
        answer_log = []
        answer_logs = ExamAnswerLog.objects.filter(main=instance).order_by('detail__order')
        for al in answer_logs:
            item = {
                'id':al.id,
                'status':al.status,
            }
            answer_log.append(item)
        ranks = []
        rank_data = ExamLog.objects.filter(exam=instance.exam).order_by('rank').values('user__name','scores','rank')
        for rank in rank_data:
            item = {
                'name':rank['user__name'],
                'scores':rank['scores'],
                'rank':rank['rank'],
            }
            ranks.append(item)
        result = {
            'question': serializer.data,
            'answer_log': answer_log,
            'ranks': ranks,
        }
        return response_ok(result)

    @action(methods=['get'], detail=False)
    def get_home_exam(self, request):
        start_time = timezone.now() + datetime.timedelta(minutes=30)
        queryset = ExamLog.objects.filter(delete=False,
                                          type=ExamLog.FORMAL,
                                          exam__exam_time__lte=start_time,
                                          user=request.user,
                                          exam__exam_end_time__gte=timezone.now()
                                          )
        data = []
        for exam_log in queryset:
            if exam_log.exam.exam_time < timezone.now() < exam_log.exam.exam_end_time:
                name = '您有一个考试，正在进行中，点击这里立即参加！'
                id = exam_log.id
            else:
                time = (exam_log.exam.exam_time - timezone.now()).seconds
                name = '您有一个考试，将在{}分钟后开始，请做好准备！'.format(int(time/60) + 1)
                id = ''
            item = {
                'id':id,
                'name':name,
                'exam_end_time':exam_log.exam.exam_end_time,
            }
            data.append(item)
        return response_ok(data)

    @action(methods=['get'], detail=False)
    def get_exam(self, request):
        start_time = timezone.now() + datetime.timedelta(minutes=30)
        queryset = ExamLog.objects.filter(delete=False,
                                          type=ExamLog.FORMAL,
                                          exam__exam_time__lte=start_time,
                                          user=request.user,
                                          exam__exam_end_time__gte=timezone.now()
                                          )
        data = []
        for exam_log in queryset:
            item = {
                'id':exam_log.id,
                'name':exam_log.exam.name,
                'subject':exam_log.exam.subject.name,
                'exam_time':strftime(exam_log.exam.exam_time),
                'exam_end_time':strftime(exam_log.exam.exam_end_time),
                'duration':exam_log.exam.duration,
            }
            data.append(item)
        return response_ok(data)

    @action(methods=['post'], detail=True)
    def get_next_practise(self, request, pk):
        now_practise = request.data.get('now_practise')  # 当前提交的模拟考试明细id。第一题或继续答题时，该参数为空
        answers = json.loads(request.data.get('answers'))  # 答案, 第一题或继续答题时，该参数为空
        next_practise = request.data.get('next_practise')  # 下一题id,首次加载第一题，传空

        try:
            with transaction.atomic():
                instance = self.get_object()
                # d1 = datetime.datetime.strptime(str(timezone.now().strftime('%Y-%m-%d %H:%M:%S')), '%Y-%m-%d %H:%M:%S')
                # d2 = datetime.datetime.strptime(str(instance.exam.exam_time), '%Y-%m-%d %H:%M:%S')
                # d3 = datetime.datetime.strptime(str(instance.exam.exam_end_time), '%Y-%m-%d %H:%M:%S')
                # print(4444444444,(d1-d2).seconds)
                # print(555555555,(d1-d3).seconds)
                # exam_time = timezone.now() - instance.exam.exam_time
                # exam_end_time = timezone.now() - instance.exam.exam_end_time
                # print(33333333, timezone.now())
                # print(1111111111,instance.exam.exam_time, exam_time.seconds)
                # print(22222222,instance.exam.exam_end_time, exam_end_time.seconds)
                if timezone.now() < instance.exam.exam_time:
                    raise CustomError('还未到考试时间，请稍等！')
                if timezone.now() > instance.exam.exam_end_time:
                    raise CustomError('考试已结束，禁止答题！')
                # 点击下一题，保存
                if now_practise:
                    detail = ExamPaperDetail.objects.filter(id=now_practise).first()
                    if not detail:
                        raise CustomError('提交的考试习题有误，请刷新重试！')
                    now_question = detail.question
                    if len(answers) > 0:
                        answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance,
                                                                                 detail=detail, )
                        if now_question.type <= ExamQuestion.MULTIPLE:
                            # 单选、多选
                            answers.sort()
                            ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
                            for a in answers:
                                ExamAnswerOptionLog.objects.create(main=answer_log, option_id=a)
                        elif now_question.type == ExamQuestion.FILL:
                            # 填空
                            answers_len = len(answers)
                            ExamAnswerFillLog.objects.filter(main=answer_log).delete()
                            for a in range(0, answers_len):
                                ExamAnswerFillLog.objects.create(main=answer_log, content=answers[a], order=a + 1)
                        else:
                            # 判断
                            if answers[0] == 1:
                                answer_log.status = ExamAnswerLog.RIGHT
                            else:
                                answer_log.status = ExamAnswerLog.WRONG
                            answer_log.save()
                    else:
                        try:
                            answer_log = ExamAnswerLog.objects.get(main=instance, detail=detail)
                            ExamAnswerOptionLog.objects.filter(main=answer_log).delete()
                            ExamAnswerFillLog.objects.filter(main=answer_log).delete()
                            answer_log.status = ExamAnswerLog.NOTDONE
                            answer_log.save()
                        except ExamAnswerLog.DoesNotExist:
                            # traceback.print_exc()
                            pass

                question_data = {}
                # 返回下一题
                if next_practise:
                    detail = ExamPaperDetail.objects.filter(id=next_practise, main=instance.exampaper,
                                                            delete=False).first()
                else:
                    detail = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).first()

                if detail:
                    question = detail.question
                    question_data = {
                        'id': detail.id,
                        'question': question.id,
                        'title': question.title,
                        'next_type': question.type,  # 下一题习题类别
                        'next_number': detail.order + 1,  # 下下一题序号，
                        'option': [],
                    }

                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=detail).first()
                    if question.type == ExamQuestion.JUDGMENT:
                        item1 = {
                            'id': 1,
                            'content': '正确',
                            'answer': True if answer_log and answer_log.status == ExamAnswerLog.RIGHT else False
                        }
                        item0 = {
                            'id': 0,
                            'content': '错误',
                            'answer': True if answer_log and answer_log.status == ExamAnswerLog.WRONG else False
                        }
                        question_data['option'].append(item1)
                        question_data['option'].append(item0)
                    elif question.type <= ExamQuestion.MULTIPLE:
                        rows = ExamQuestionOption.objects.filter(main=question, delete=False)
                        for row in rows:
                            option_log = ExamAnswerOptionLog.objects.filter(main=answer_log, option=row).first()
                            item = {
                                'id': row.id,
                                'content': row.content,
                                'answer': option_log and True or False
                            }
                            question_data['option'].append(item)
                    elif question.type == ExamQuestion.FILL:
                        rows = ExamQuestionFill.objects.filter(main=question, delete=False)
                        for row in rows:
                            option_log = ExamAnswerFillLog.objects.filter(main=answer_log, order=row.order).first()
                            item = {
                                'id': row.order,  # 填空题序号
                                'content': option_log and option_log.content or '',
                            }
                            question_data['option'].append(item)

                # 右侧习题类别列表
                # 单选、多选、填空。选择答案后，可能会把答案清空，得加上NOTDONE过滤
                questions = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False).values_list('id',
                                                                                                              flat=True)
                single_questions_list = []
                for single in questions.filter(question__type=ExamQuestion.SINGLE):
                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=single).exclude(status=ExamAnswerLog.NOTDONE)
                    single_questions_list.append(
                        {
                            'question_id': single,
                            'complete': answer_log and True or False,
                        }
                    )
                # 多选题
                multiple_questions_list = []
                for multiple in questions.filter(question__type=ExamQuestion.MULTIPLE):
                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=multiple).exclude(status=ExamAnswerLog.NOTDONE)
                    multiple_questions_list.append(
                        {
                            'question_id': multiple,
                            'complete': answer_log and True or False,
                        }
                    )
                # 填空题
                fill_questions_list = []
                for fill in questions.filter(question__type=ExamQuestion.FILL):
                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=fill).exclude(status=ExamAnswerLog.NOTDONE)
                    fill_questions_list.append(
                        {
                            'question_id': fill,
                            'complete': answer_log and True or False,
                        }
                    )
                # 判断题
                judgment_questions_list = []
                for judgment in questions.filter(question__type=ExamQuestion.JUDGMENT):
                    answer_log = ExamAnswerLog.objects.filter(main=instance, detail=judgment).exclude(status=ExamAnswerLog.NOTDONE)
                    judgment_questions_list.append(
                        {
                            'question_id': judgment,
                            'complete': answer_log and True or False,
                        }
                    )
                result = {
                    'question_data': question_data,  # 下一题练习题
                    'single_questions_list': single_questions_list,  # 单选
                    'multiple_questions_list': multiple_questions_list,  # 多选
                    'fill_questions_list': fill_questions_list,  # 填空
                    'judgment_questions_list': judgment_questions_list,  # 判断
                }
                return response_ok(result)
        except CustomError as e:
            return response_error(e.get_error_msg())
        except Exception as e:
            traceback.print_exc()
            return response_error(str(e))

    @action(methods=['post'], detail=True)
    def submit_practise(self, request, pk):
        # 习题交卷,把上个接口的判断答案，放到此处
        try:
            instance = self.get_object()
            # if timezone.now() > instance.exam.exam_end_time:
            #     raise CustomError('考试已结束，禁止答题！')
            with transaction.atomic():
                paper_details = ExamPaperDetail.objects.filter(main=instance.exampaper, delete=False)
                for detail in paper_details:
                    # 创建模拟考试未答题记录,如果没有找到答案记录，则该题保留未答状态
                    answer_log, create = ExamAnswerLog.objects.get_or_create(main=instance, detail=detail)
                    # answer_logs = ExamAnswerLog.objects.filter(main=instance)
                    # for answer_log in answer_logs:
                    question = detail.question
                    if question.type == ExamQuestion.SINGLE:
                        # 单选
                        answers = ExamAnswerOptionLog.objects.filter(main=answer_log).first()
                        if answers:
                            if answers.option.right:
                                answer_log.status = ExamAnswerLog.RIGHT
                                instance.single_answer_count += 1
                            else:
                                answer_log.status = ExamAnswerLog.WRONG
                                ErrorBook.add_error(question, request.user, answer_log)
                    elif question.type == ExamQuestion.MULTIPLE:
                        # 多选
                        answers = ExamAnswerOptionLog.objects.filter(main=answer_log).order_by('option_id').values_list(
                            'option_id', flat=True)
                        if answers:
                            right = ExamQuestionOption.objects.filter(main=question, right=True,
                                                                      delete=False).values_list('id', flat=True)
                            if list(answers) == list(right):
                                answer_log.status = ExamAnswerLog.RIGHT
                                instance.multiple_answer_count += 1
                            else:
                                answer_log.status = ExamAnswerLog.WRONG
                                ErrorBook.add_error(question, request.user, answer_log)
                    elif question.type == ExamQuestion.FILL:
                        # 填空
                        fill_logs = ExamAnswerFillLog.objects.filter(main=answer_log)
                        right = True
                        if fill_logs:
                            for fill_log in fill_logs:
                                right_answer = ExamQuestionFill.objects.filter(main=question, content=fill_log.content,
                                                                               order=fill_log.order, delete=False)
                                if not right_answer:
                                    right = False
                                    break
                            if right:
                                answer_log.status = ExamAnswerLog.RIGHT
                                instance.fill_answer_count += 1
                            else:
                                answer_log.status = ExamAnswerLog.WRONG
                                ErrorBook.add_error(question, request.user, answer_log)
                    else:
                        # 判断
                        if answer_log.status != ExamAnswerLog.NOTDONE:
                            if question.judgment == (answer_log.status == ExamAnswerLog.RIGHT):
                                answer_log.status = ExamAnswerLog.RIGHT
                                instance.judgment_answer_count += 1
                            else:
                                answer_log.status = ExamAnswerLog.WRONG
                                ErrorBook.add_error(question, request.user, answer_log)
                    answer_log.save()

                instance.submit_time = timezone.now()
                use_time = instance.submit_time - instance.exam_time
                instance.use_time = use_time.seconds

                single_answer_scores = instance.single_answer_count * instance.exampaper.single_scores
                multiple_answer_scores = instance.multiple_answer_count * instance.exampaper.multiple_scores
                fill_answer_scores = instance.fill_answer_count * instance.exampaper.fill_scores
                judgment_answer_scores = instance.judgment_answer_count * instance.exampaper.judgment_scores

                instance.single_answer_scores = single_answer_scores
                instance.multiple_answer_scores = multiple_answer_scores
                instance.fill_answer_scores = fill_answer_scores
                instance.judgment_answer_scores = judgment_answer_scores
                instance.scores = single_answer_scores + judgment_answer_scores + multiple_answer_scores + fill_answer_scores
                # 计算排名
                up_rank = ExamLog.objects.filter(exam=instance.exam, scores__gte=instance.scores).count()
                instance.rank = up_rank + 1
                ExamLog.objects.filter(exam=instance.exam, scores__lte=instance.scores).update(rank=F('rank') + 1)
                instance.save()

                instance.exampaper.did_count += 1
                instance.exampaper.save()

                SysLog.objects.addnew(request.user, SysLog.INSERT, u"提交模拟考试题,id=%d" % (instance.id))
        except CustomError as e:
            return response_error(e.get_error_msg())
        except Exception as e:
            traceback.print_exc()
            return response_error(str(e))
        return response_ok()


class ExamQuestionFeedbackViewSet(CustomModelViewSet):
    permission_classes = [IsStaff, ]
    queryset = ExamQuestionFeedback.objects.filter()
    serializer_class = ExamQuestionFeedbackSerializer

    def perform_create(self, serializer):
        super(ExamQuestionFeedbackViewSet, self).perform_create(serializer)
        instance = serializer.instance
        validated_data = serializer.validated_data
        SysLog.objects.addnew(self.request.user, SysLog.INSERT, u'添加试题错误反馈，id=%d' % instance.id, validated_data)
