
from django.core.validators import MinValueValidator, MaxValueValidator
from rest_framework import serializers
from utils.validators import IncludeExcludeOnlyValidator, dict_validator
from . import validators
from .models import Question, QUESTION_TYPE_MULTIPLE_CHOICE
from .validators import question_format_validator, tags_validator, question_type_validator, \
    questions_sort_by_validator, meta_validator


# choice = [("only", "only"),
#           ("exclude", "exclude"),
#           ("include", "include"), ]


############################## API Serializers ##############################


class QuestionContentInputSerializer(serializers.Serializer):
    keywords = serializers.CharField(
        max_length=600, required=False, allow_null=True, allow_blank=True)
    question_text = serializers.CharField()
    format = serializers.CharField(
        max_length=20, validators=[question_format_validator])
    # validator
    # If we use JSONField, choices=[] will return 500 error because it cannot be stored in django.contrib.postgres.fields.HStoreField
    # If we use HStoreField, the value will not be correctly parsed
    choices = serializers.JSONField(
        validators=[dict_validator], required=False)
    correct_choices = serializers.ListField(
        child=serializers.CharField(), required=False)
    question_type = serializers.CharField(
        max_length=20, validators=[question_type_validator])
    input_rules = serializers.JSONField()
    tags = serializers.JSONField(validators=[tags_validator])
    solution = serializers.CharField(required=False)
    meta_data = serializers.JSONField(
        validators=[meta_validator], required=False)

    def validate(self, data):
        if data.get('question_type') == QUESTION_TYPE_MULTIPLE_CHOICE:
            if data.get('choices') is None:
                raise serializers.ValidationError(
                    {'choices': 'choices is required when question_type is "multiple-choice"'})
            if data.get('correct_choices') is None:
                raise serializers.ValidationError(
                    {'correct_choices': 'correct_choices is required when question_type is "multiple-choice"'})
            validators.choices_validator(
                data.get('choices'), data.get('correct_choices'))

        validators.input_rules_validator(data.get('input_rules'), choices=data.get(
            'choices'), question_type=data.get('question_type'))

        return data


class CreateQuestionApiInputSerializer(QuestionContentInputSerializer):
    question_bank_id = serializers.UUIDField()


class CreateQuestionBulkApiInputSerializer(serializers.Serializer):
    question_bank_id = serializers.UUIDField()
    questions = QuestionContentInputSerializer(many=True)


class EditQuestionApiInputSerializer(QuestionContentInputSerializer):
    question_id = serializers.UUIDField()


class DeleteQuestionApiInputSerializer(serializers.Serializer):
    question_id = serializers.UUIDField()


class QuestionsListApiInputSerializer(serializers.Serializer):

    question_bank_id = serializers.UUIDField()
    context_institute_id = serializers.UUIDField()
    skip = serializers.IntegerField(validators=[MinValueValidator(0)])
    take = serializers.IntegerField(
        validators=[MinValueValidator(1), MaxValueValidator(100)])
    q = serializers.CharField(max_length=100, required=False, allow_null=True)
    archived_filter = serializers.CharField(
        validators=[IncludeExcludeOnlyValidator()])
    # TODO validators
    tag_filters = serializers.JSONField(required=False)
    old_tag_filters = serializers.JSONField(required=False)
    question_type = serializers.CharField(
        validators=[question_type_validator], required=False)
    sort_by = serializers.CharField(validators=[questions_sort_by_validator])
    auto_correctable_filter = serializers.CharField(
        validators=[IncludeExcludeOnlyValidator()])


class QuestionsGetApiInputSerializer(serializers.Serializer):

    question_id = serializers.UUIDField()
    context_institute_id = serializers.UUIDField()


class EditQuestionBulkApiInputSerializer(serializers.Serializer):
    question_bank_id = serializers.UUIDField()
    context_institute_id = serializers.UUIDField()

    commit = serializers.BooleanField()
    action = serializers.ChoiceField(
        choices=[("update", "Update"), ("remove", "Remove"), ("add", "Add")])

    current_key = serializers.CharField(required=False)
    current_value = serializers.CharField(required=False)
    incoming_key = serializers.CharField(required=False)
    incoming_value = serializers.CharField(required=False)


############################## Model Serializers ##############################


class QuestionModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = Question
        fields = ['id', 'keywords', 'tags', 'auto_correctable', 'question_text', 'format',
                  'question_type', 'choices', 'correct_choices',
                  'input_rules', 'created_at', 'modified_at', 'solution']
