from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from lms.courses.models import Course
from lms.tracker.models import EnrollmentTrackerQueue
from lms.tracker.serializers import EnrollmentTrackerQueueNestedLabSerializer

from ..models import Enrollment, EnrollSurvey


# API Serializers
# ===============
class EnrollmentListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Enrollment
        fields = (
            'id', 'survey_id', 'enroll_type', 'name', 'summary', 'options', 'is_default', 'is_active',
            'created', 'modified',
        )
        read_only_fields = fields


class EnrollmentDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = Enrollment
        fields = (
            'id', 'course_id', 'survey_id', 'enroll_type', 'name', 'summary', 'options',
            'is_default',
            'created', 'modified',
        )
        read_only_fields = fields


# LabAPI Serializers
# ==================
class EnrollmentListLabSerializer(serializers.ModelSerializer):
    class Meta:
        model = Enrollment
        fields = (
            'id', 'survey_id', 'enroll_type', 'name', 'summary', 'options',
            'is_active', 'is_default',
            'created', 'modified',
        )
        read_only_fields = fields


class EnrollmentDetailLabSerializer(serializers.ModelSerializer):
    class Meta:
        model = Enrollment
        fields = (
            'id', 'course_id', 'survey_id', 'enroll_type', 'name', 'summary', 'options',
            'is_active', 'is_default',
            'created', 'modified',
        )
        read_only_fields = fields


class EnrollmentCreateLabSerializer(serializers.ModelSerializer):
    course_id = serializers.PrimaryKeyRelatedField(
        source='course', queryset=Course.objects.all(),
    )

    survey_id = serializers.PrimaryKeyRelatedField(
        source='survey', queryset=EnrollSurvey.objects.all(),
        required=False, allow_null=True,
    )

    parameters = serializers.JSONField(required=False, allow_null=True)

    class Meta:
        model = Enrollment
        fields = (
            'course_id', 'survey_id', 'enroll_type', 'name', 'summary',
            'is_active', 'is_default', 'parameters',
        )

    def validate(self, attrs):
        parameters = attrs.pop('parameters', {})
        instance = Enrollment(**attrs)
        instance.clean()

        # дополнительные параметры
        parameters_errors = {}
        if instance.enroll_type == Enrollment.TYPE_TRACKER:
            tracker_queue_serializer = EnrollmentTrackerQueueNestedLabSerializer(
                data=parameters.get('tracker_queues', []),
                many=True,
                context=self.context,
            )
            if not tracker_queue_serializer.is_valid(raise_exception=False):
                parameters_errors['tracker_queues'] = tracker_queue_serializer.errors

        if parameters_errors:
            raise ValidationError({'parameters': parameters_errors})

        attrs['parameters'] = parameters

        return attrs

    def create(self, validated_data):
        parameters = validated_data.pop('parameters', {})
        enrollment = Enrollment.objects.create(**validated_data)

        if enrollment.enroll_type == Enrollment.TYPE_TRACKER:
            for queue_data in parameters.get('tracker_queues', []):
                EnrollmentTrackerQueue.objects.create(
                    enrollment=enrollment, **queue_data
                )

        return enrollment


class EnrollmentCreateWithoutTypeLabSerializer(serializers.ModelSerializer):
    course_id = serializers.PrimaryKeyRelatedField(
        source='course', queryset=Course.objects.all(),
    )

    survey_id = serializers.PrimaryKeyRelatedField(
        source='survey', queryset=EnrollSurvey.objects.all(),
        required=False, allow_null=True,
    )

    class Meta:
        model = Enrollment
        fields = (
            'course_id', 'survey_id', 'name', 'summary',
            'is_active', 'is_default',
        )


class EnrollmentUpdateLabSerializer(serializers.ModelSerializer):
    survey_id = serializers.PrimaryKeyRelatedField(
        source='survey', queryset=EnrollSurvey.objects.all(),
        required=False, allow_null=True,
    )

    class Meta:
        model = Enrollment
        fields = (
            'survey_id', 'name', 'summary', 'is_active', 'is_default',
        )
