"""This module contains the apiV2-related serializers of the ``evaluations`` app"""

from django.core.exceptions import MultipleObjectsReturned

from rest_framework import serializers

from mtp.apps.accounts.models import MTPUser
from mtp.apps.trainings.apiv2.serializers import TrainingActivitySerializer

from ..models import Criterion, Evaluation, Exercise, Rating


class CriterionSerializer(serializers.ModelSerializer):
    """Serializer for the ``Criteria`` model"""

    type = serializers.CharField(source='criterion_type')

    class Meta:
        model = Criterion
        fields = (
            'id',
            'type',
            'description'
        )


class ExerciseSerializer(serializers.ModelSerializer):
    """Serializer for the ``Exercise`` model"""

    criteria = CriterionSerializer(many=True)

    class Meta:
        model = Exercise
        fields = (
            'id',
            'name',
            'description',
            'start_range',
            'end_range',
            'step',
            'criteria'
        )


class EvaluationSerializer(TrainingActivitySerializer):
    """Serializer for the ``Evaluation`` model"""

    exercises = ExerciseSerializer(many=True, read_only=True)
    type = serializers.CharField(source='evaluation_type')

    class Meta:
        model = Evaluation
        fields = TrainingActivitySerializer.Meta.fields + (
            'type',
            'exercises'
        )


class RatingSerializer(serializers.ModelSerializer):
    """Serializer for the ``Rating`` model"""

    session = serializers.PrimaryKeyRelatedField(
        read_only=True
    )
    judge = serializers.PrimaryKeyRelatedField(
        read_only=True
    )
    criterion = serializers.PrimaryKeyRelatedField(
        queryset=Criterion.objects.non_deleted()
    )
    trainee = serializers.PrimaryKeyRelatedField(
        queryset=MTPUser.objects.non_deleted()
    )

    class Meta:
        model = Rating
        fields = (
            'id',
            'session',
            'judge',
            'criterion',
            'trainee',
            'score',
            'text',
        )

    def create(self, validated_data):
        """Create or update the rating instance from the validated data

        For the parameters, see ``rest_framework.serializers.ModelSerializer.create``
        """

        try:
            rating, _ = Rating.objects.update_or_create(
                session_id=self.context['session'].id,
                judge_id=self.context['judge'].id,
                criterion_id=validated_data['criterion'].id,
                trainee_id=validated_data['trainee'].id,
                defaults={
                    'score': validated_data.get('score'),
                    'text': validated_data.get('text', '')
                }
            )
        except MultipleObjectsReturned:
            # Wow, something is really wrong there...
            raise serializers.ValidationError(
                'Got multiple ratings for the current session / judge / criterion'
            )

        return rating
