# coding=utf-8
import json
import traceback
from django.db.models import Sum, F
from rest_framework.decorators import action
from rest_framework.serializers import ValidationError
from rest_framework.views import APIView
from django.db import transaction
from django.db.models import Q
from utils.custom_modelviewset import CustomModelViewSet
from utils import response_ok, response_error
from utils.permission import IsAdministrator, IsStaff
from apps.examination.examquestion.serializers import *
from apps.examination.examquestion.filters import *
from apps.system.models import SysLog
from apps.foundation.serializers import SubjectSerializer, ChapterSerializer, SubjectSimpleSerializer, \
    ChapterSimpleSerializer, Subject
from apps.practise.practiselog.models import *
from apps.practise.practiselog.serializers import PractiseLogSerializer


class PractiseLogViewSet(CustomModelViewSet):
    permission_classes = [IsStaff, ]
    queryset = PractiseLog.objects.filter()
    serializer_class = PractiseLogSerializer

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

    def create(self, request, *args, **kwargs):
        subject = request.data.get('subject')
        chapter = request.data.get('chapter')
        type = PractiseLog.CHAPTER
        try:
            with transaction.atomic():
                if not chapter:
                    # 进入练习题，没有选择章节，使用该科目下的第一个章节
                    # chapter = Chapter.objects.filter(subject=subject, delete=False).order_by('id').first()
                    type = PractiseLog.SUBJECT

                data = {
                    'subject': int(subject),
                    'chapter': chapter and int(chapter) or None,
                    'type': type,
                    'create_user': request.user.id,
                    'submit_time': timezone.now()
                }
                serializer = PractiseLogSerializer(data=data)
                if serializer.is_valid(raise_exception=True):
                    instance = serializer.save()
                    result = {
                        'practise': instance.id,  # 练习题 id
                    }
                    return response_ok(result)
        except ValidationError as e:
            traceback.print_exc()
            return response_error('数据格式有误')

    @action(methods=['post'], detail=True)
    def get_next_practise(self, request, pk):
        now_practise = request.data.get('now_practise')  # 当前提交的练习题。第一题或继续答题时，该参数为空
        answers = json.loads(request.data.get('answers'))  # 答案, 第一题或继续答题时，该参数为空
        next_number = request.data.get('next_number') or 0  # 下一题序号， 第一题提交为空，不在使用
        next_practise = request.data.get('next_practise')  # 下一题id,首次加载第一题，传空
        try:
            with transaction.atomic():
                instance = self.get_object()
                # 点击下一题，保存、判断当前习题答案
                if now_practise:
                    now_question = ExamQuestion.objects.filter(id=now_practise).first()
                    if not now_question:
                        raise CustomError('提交的习题有误，请刷新重试！')
                    if len(answers) > 0:
                        answer_log, create = PractiseAnswerLog.objects.get_or_create(main=instance,
                                                                                     question=now_question, )
                        if now_question.type == ExamQuestion.SINGLE:
                            # 单选
                            PractiseAnswerOptionLog.objects.filter(main=answer_log).delete()
                            answer = answers[0]
                            PractiseAnswerOptionLog.objects.create(main=answer_log, option_id=answer)
                            right = ExamQuestionOption.objects.filter(main=now_question, id=answer, right=True,
                                                                      delete=False)
                            if right:
                                answer_log.status = PractiseAnswerLog.RIGHT
                            else:
                                answer_log.status = PractiseAnswerLog.WRONG
                        elif now_question.type == ExamQuestion.MULTIPLE:
                            # 多选
                            answers.sort()
                            PractiseAnswerOptionLog.objects.filter(main=answer_log).delete()
                            for a in answers:
                                PractiseAnswerOptionLog.objects.create(main=answer_log, option_id=a)
                            right = ExamQuestionOption.objects.filter(main=now_question, right=True,
                                                                      delete=False).values_list('id', flat=True)
                            list(right).sort()
                            if answers == right:
                                answer_log.status = PractiseAnswerLog.RIGHT
                            else:
                                answer_log.status = PractiseAnswerLog.WRONG
                        elif now_question.type == ExamQuestion.FILL:
                            # 填空
                            answers_len = len(answers)
                            right = 1
                            PractiseAnswerFillLog.objects.filter(main=answer_log).delete()
                            for a in range(0, answers_len):
                                PractiseAnswerFillLog.objects.create(main=answer_log, content=answers[a], order=a + 1)
                                right_answer = ExamQuestionFill.objects.filter(main=now_question, content=answers[a],
                                                                               order=a + 1)
                                if not right_answer:
                                    # 有一个填空错误，整题错误
                                    right = 0
                            if right:
                                answer_log.status = PractiseAnswerLog.RIGHT
                            else:
                                answer_log.status = PractiseAnswerLog.WRONG
                        else:
                            # 判断
                            if now_question.judgment == (answers[0] == 1):
                                answer_log.status = PractiseAnswerLog.RIGHT
                            else:
                                answer_log.status = PractiseAnswerLog.WRONG
                        instance.total_count += 1
                        # 第一题
                        if not instance.begin_answer:
                            instance.begin_answer = answer_log
                        instance.end_answer = answer_log
                        instance.submit_time = timezone.now()
                        instance.save()
                        answer_log.save()
                    else:
                        try:
                            answer_log = PractiseAnswerLog.objects.get(main=instance, question=now_question, )
                            PractiseAnswerOptionLog.objects.filter(main=answer_log).delete()
                            PractiseAnswerFillLog.objects.filter(main=answer_log).delete()
                            answer_log.status = None
                            answer_log.save()
                        except PractiseAnswerLog.DoesNotExist:
                            # traceback.print_exc()
                            pass

                question_data = {}
                if instance.type == PractiseLog.SUBJECT:
                    questions = ExamQuestion.objects.filter(chapter__subject=instance.subject, delete=False).order_by(
                        'type')
                else:
                    questions = ExamQuestion.objects.filter(chapter=instance.chapter, delete=False).order_by('type')
                # 返回下一题
                if next_practise:
                    question = questions.filter(id=next_practise).first()
                else:
                    # 首次加载，选择第一个题
                    question = questions.filter().first()

                if question:
                    question_data = {
                        'id': question.id,
                        'title': question.title,
                        'next_type': question.type,  # 下一题习题类别
                        'next_number': int(next_number) + 1,  # 下下一题序号，
                        'option': [],
                    }
                    answer_log = PractiseAnswerLog.objects.filter(main=instance, question=question).first()
                    if question.type == ExamQuestion.JUDGMENT:
                        item1 = {
                            'id': 1,
                            'content': '正确',
                            'answer': True if answer_log and answer_log.status == PractiseAnswerLog.RIGHT else False
                        }
                        item0 = {
                            'id': 0,
                            'content': '错误',
                            'answer': True if answer_log and answer_log.status == PractiseAnswerLog.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 = PractiseAnswerOptionLog.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 = PractiseAnswerFillLog.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)

                # 右侧习题类别列表
                # 单选题
                # 单选、多选、填空。选择答案后，可能会把答案清空，得加上status__isnull=False过滤
                questions = questions.values_list('id', flat=True)
                single_questions_list = []
                for single in questions.filter(type=ExamQuestion.SINGLE):
                    answer_log = PractiseAnswerLog.objects.filter(main=instance, question_id=single,
                                                                  status__isnull=False)
                    single_questions_list.append(
                        {
                            'question_id': single,
                            'complete': answer_log and True or False,
                        }
                    )
                # 多选题
                multiple_questions_list = []
                for multiple in questions.filter(type=ExamQuestion.MULTIPLE):
                    answer_log = PractiseAnswerLog.objects.filter(main=instance, question_id=multiple,
                                                                  status__isnull=False)
                    multiple_questions_list.append(
                        {
                            'question_id': multiple,
                            'complete': answer_log and True or False,
                        }
                    )
                # 填空题
                fill_questions_list = []
                for fill in questions.filter(type=ExamQuestion.FILL):
                    answer_log = PractiseAnswerLog.objects.filter(main=instance, question_id=fill, status__isnull=False)
                    fill_questions_list.append(
                        {
                            'question_id': fill,
                            'complete': answer_log and True or False,
                        }
                    )
                # 判断题
                judgment_questions_list = []
                for judgment in questions.filter(type=ExamQuestion.JUDGMENT):
                    answer_log = PractiseAnswerLog.objects.filter(main=instance, question_id=judgment)
                    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()

            with transaction.atomic():
                right_count = PractiseAnswerLog.objects.filter(main=instance, status=PractiseAnswerLog.RIGHT).count()
                wrong_count = PractiseAnswerLog.objects.filter(main=instance, status=PractiseAnswerLog.WRONG).count()
                instance.right_count = right_count
                instance.wrong_count = wrong_count
                instance.submit_time = timezone.now()
                instance.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 DictView(APIView):
    permission_classes = [IsStaff, ]

    def get(self, request):
        data = []
        subjects = Subject.objects.filter(delete=False).values('id', 'name').order_by('id')
        for subject in subjects:
            chapters = ChapterSimpleSerializer(
                Chapter.objects.filter(delete=False, subject__delete=False, subject_id=subject['id']).order_by('id'),
                many=True).data
            item = {
                'id': subject['id'],
                'name': subject['name'],
                'chapters': chapters,
            }
            data.append(item)
        return response_ok(data)
