"""Test the serializers of the ``roleplays`` app"""

from rest_framework import serializers

from ..models import Criterion, Rating
from ..serializers import RatingSerializer

from .test_cases import RoleplayTestCase


class RoleplaySerializersTestCase(RoleplayTestCase):
    """Test case that tests the ``Roleplay`` serializers."""

    def get_ratings_initial_data_as_list(self):
        """Shortcut method to get the ratings initial data as a list of dicts."""

        current_step = self.roleplay.steps.first()

        ratings_list = []

        # The ``QUANTITATIVE`` criteria.
        for criterion in current_step.criteria.quantitative():
            ratings_list.append({ 
                'criterion': criterion.pk,
                'score': 2
            })

        # The ``BOOLEAN`` criteria.
        for criterion in current_step.criteria.boolean():
            ratings_list.append({ 
                'criterion': criterion.pk,
                'score': 100
            })

        return ratings_list

    def test_rating_list_serializer_with_list_is_correct(self):
        """Test the rating list serializer with a list object"""

        ratings_list = self.get_ratings_initial_data_as_list()

        serialized_ratings = RatingSerializer(data=ratings_list, many=True)

        self.assertTrue(serialized_ratings.is_valid())
        serialized_ratings.save(
            training_session=self.training_session,
            trainee=self.trainee
        )

        self.assertEqual(
            Rating.objects.filter(trainee=self.trainee).count(),
            len(ratings_list)
        )

    def get_ratings_initial_data_as_dict(self):
        """Shortcut method to get the ratings initial data as a dict object"""

        current_step = self.roleplay.steps.first()

        # We need some ratings.
        ratings = []

        # The ``QUANTITATIVE`` criteria.
        for criterion in current_step.criteria.quantitative():
            ratings.append({
                'criterion': criterion.pk,
                'score': 2,
            })

        # The ``BOOLEAN`` criteria.
        for criterion in current_step.criteria.boolean():
            ratings.append({ 
                'criterion': criterion.pk,
                'score': 100
            })

        return ratings

    def test_rating_list_serializer_with_dict_is_correct(self):
        """Test the rating list serializer with a dict object"""

        ratings = self.get_ratings_initial_data_as_dict()
        ratings_item_length = len(ratings)

        serialized_ratings = RatingSerializer(data=ratings, many=True)

        self.assertTrue(serialized_ratings.is_valid())
        ratings = serialized_ratings.save(
            training_session=self.training_session,
            trainee=self.trainee
        )
        
        # The serialized ratings have been correctly saved
        self.assertEqual(
            Rating.objects.filter(trainee=self.trainee).count(),
            ratings_item_length
        )

    def test_rating_list_serializer_with_dict_is_incorrect(self):
        """Test for the exceptions raised by the serializer if the input
        is incorrect"""

        ratings = self.get_ratings_initial_data_as_dict()

        # We remove the ``ratings``.
        ratings = [{'this is not a rating': 'no, this is not'}]
        serialized_ratings = RatingSerializer(data=ratings, many=True)
        self.assertFalse(serialized_ratings.is_valid())

        ratings = self.get_ratings_initial_data_as_dict()
