"""This module holds the serializers related test cases for the ``questionnaires`` app"""

from mtp.apps.questionnaires.factories import (
    ChoicesAnswerFactory,
    ImageChoicesQuestionFactory,
    OpenAnswerFactory,
    OpenQuestionFactory,
)
from mtp.apps.questionnaires.models import (
    ChoicesAnswer,
    OpenAnswer,
)
from mtp.apps.questionnaires.tests.test_cases import QuestionnairesTestCase

from ..serializers import (
    ChoicesAnswerSerializer,
    ChoicesQuestionSerializer,
    ChoiceSerializer,
    ImageChoicesQuestionSerializer,
    OpenAnswerSerializer,
    QuizSerializer,
    ReadAnswerSerializer,
)


class QuestionnairesSerializersTestCase(QuestionnairesTestCase):
    """Test case for the serializers of the ``questionnaires`` app"""

    def test_choice_serializer_from_instance_should_work(self):
        """Test that the ``ChoiceSerializer`` should work"""

        choice = self.choices_questions[0].choices.first()

        serialized_choice = ChoiceSerializer(choice)

        self.assertDictEqual(
            serialized_choice.data,
            {
                'id': choice.id,
                'label': choice.label,
                'is_valid': choice.is_valid,
                'sort_order': choice.sort_order
            }
        )

    def test_choice_question_serializer_from_instance_should_work(self):
        """Test that the ``ChoicesQuestionSerializer`` is working correctly"""

        serialized_choices_question = ChoicesQuestionSerializer(self.choices_questions[0])

        self.assertDictEqual(
            serialized_choices_question.data,
            {
                'id': self.choices_questions[0].id,
                'label': self.choices_questions[0].label,
                'points': self.choices_questions[0].points,
                'question_type': self.choices_questions[0].question_type,
                'is_multiple_choices': self.choices_questions[0].is_multiple_choices,
                'sort_order': self.choices_questions[0].sort_order,
                'choices': [
                    ChoiceSerializer(choice).data
                    for choice in self.choices_questions[0].choices.non_deleted()
                ]
            }
        )

    def test_image_question_serializer_from_instance_should_work(self):
        """Test that the ``ImageQuestionSerializer`` is working correctly"""

        image_question = ImageChoicesQuestionFactory(questionnaire=self.quiz)

        serialized_image_question = ImageChoicesQuestionSerializer(image_question)

        self.assertDictEqual(
            serialized_image_question.data,
            {
                'id': image_question.id,
                'label': image_question.label,
                'points': image_question.points,
                'question_type': image_question.question_type,
                'is_multiple_choices': image_question.is_multiple_choices,
                'sort_order': image_question.sort_order,
                'image': None,
                'choices': [
                    ChoiceSerializer(choice).data
                    for choice in image_question.choices.non_deleted()
                ]
            }
        )

    def test_quiz_serializer_from_instance_should_work(self):
        """Test that the ``QuizSerializer`` is working correctly"""

        serialized_quiz = QuizSerializer(self.quiz)

        self.assertDictEqual(
            serialized_quiz.data,
            {
                'id': self.quiz.id,
                'name': self.quiz.name,
                'description': self.quiz.description,
                'activity_type': self.quiz.activity_type,
                'sort_order': self.quiz.sort_order,
                'session': self.quiz.session_id,
                'training': self.quiz.training_id,
                'is_score_displayed': self.quiz.is_score_displayed,
                'is_questions_order_random': self.quiz.is_questions_order_random,
                'are_questions_mandatory': self.quiz.are_questions_mandatory,
                'questions': [
                    question.serializer_class(question).data
                    for question in self.quiz.questions.non_deleted()
                ]
            }
        )

    def test_choices_answer_from_instance_should_work(self):
        """Test that the ``ChoicesAnswer`` serializer from instance is working correctly"""

        first_question = self.choices_questions[0]
        first_choice = first_question.choices.first()

        choices_answer = ChoicesAnswerFactory(
            user=self.trainee,
            session=self.training_session,
            question=first_question,
        )

        choices_answer.choices.add(first_choice)

        serialized_choices_answer = ChoicesAnswerSerializer(choices_answer)

        self.assertDictEqual(
            serialized_choices_answer.data,
            {
                'id': choices_answer.id,
                'choices': [
                    first_choice.id
                ],
                'question': first_question.id,
                'question_type': first_question.question_type,
                'session': self.training_session.id,
                'user': self.trainee.id
            }
        )

    def test_choices_answer_from_data_should_work(self):
        """Test that the ``ChoicesAnswer`` serializer from data should work"""

        first_question = self.choices_questions[0]
        first_choice = first_question.choices.first()

        # At first, we don't have any choices answer
        self.assertIsNone(ChoicesAnswer.objects.first())

        data = {
            'choices': [
                first_choice.id
            ],
            'question': first_question.id,
            'session': self.training_session.id,
            'user': self.trainee.id
        }

        serialized_choices_answer = ChoicesAnswerSerializer(data=data)

        self.assertTrue(serialized_choices_answer.is_valid())

        serialized_choices_answer.save()

        # Now, we should have one new choices answer
        choices_answer = ChoicesAnswer.objects.first()

        self.assertEqual(choices_answer.question, first_question)
        self.assertEqual(choices_answer.session, self.training_session)
        self.assertEqual(choices_answer.user, self.trainee)
        self.assertEqual(
            list(choices_answer.choices.values_list('id', flat=True)),
            [
                first_choice.id
            ]
        )

    def test_open_answer_from_instance_should_work(self):
        """Test that the ``OpenAnswer`` serializer from instance is working correctly"""

        open_question = OpenQuestionFactory(questionnaire=self.quiz)
        open_answer = OpenAnswerFactory(
            user=self.trainee,
            session=self.training_session,
            question=open_question,
            content='Text content of the open answer'
        )

        serialized_choices_answer = OpenAnswerSerializer(open_answer)

        self.assertDictEqual(
            serialized_choices_answer.data,
            {
                'id': open_answer.id,
                'question': open_question.id,
                'question_type': open_question.question_type,
                'session': self.training_session.id,
                'user': self.trainee.id,
                'content': 'Text content of the open answer'
            }
        )

    def test_open_answer_from_data_should_work(self):
        """Test that the ``OpenAnswer`` serializer from data is working correctly"""

        open_question = OpenQuestionFactory(questionnaire=self.quiz)

        # At first, we don't have any open answer
        self.assertIsNone(OpenAnswer.objects.first())

        data = {
            'content': 'New open answer content',
            'question': open_question.id,
            'session': self.training_session.id,
            'user': self.trainee.id
        }

        serialized_open_answer = OpenAnswerSerializer(data=data)

        self.assertTrue(serialized_open_answer.is_valid())

        serialized_open_answer.save()

        # Now, we should have one new open answer
        open_answer = OpenAnswer.objects.first()

        self.assertEqual(open_answer.question, open_question)
        self.assertEqual(open_answer.session, self.training_session)
        self.assertEqual(open_answer.user, self.trainee)
        self.assertEqual(open_answer.content, 'New open answer content')

    def test_answer_serializer_from_instance_should_work(self):
        """Test that the ``Answer`` serializer from instance is working correctly"""

        first_question = self.choices_questions[0]
        first_choice = first_question.choices.first()

        choices_answer = ChoicesAnswerFactory(
            user=self.trainee,
            session=self.training_session,
            question=first_question,
        )

        choices_answer.choices.add(first_choice)

        self.assertEqual(
            ReadAnswerSerializer(choices_answer).data,
            ChoicesAnswerSerializer(choices_answer).data
        )

        open_question = OpenQuestionFactory(questionnaire=self.quiz)
        open_answer = OpenAnswerFactory(
            user=self.trainee,
            session=self.training_session,
            question=open_question,
            content='Text content of the open answer'
        )

        self.assertEqual(
            ReadAnswerSerializer(open_answer).data,
            OpenAnswerSerializer(open_answer).data
        )
