"""Test the views of the ``roleplays`` app"""

import os

from django.conf import settings
from django.core.urlresolvers import reverse

from mtp.apps.assessments.factories import (
    CompetencyTreeFactory, CompetencyFactory, DimensionFactory
)
from mtp.apps.assessments.tests.test_cases import MTPSimpleAssessmentTestCase
from mtp.apps.common.tests.test_cases import MTPTestCase

from ..factories import RoleplayFactory, StepFactory
from ..models import Criterion, Roleplay

from .test_cases import RoleplayTestCase


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

    @classmethod
    def setUpTestData(cls):
        super().setUpTestData()

        cls.roleplay_create_url = reverse('trainings:roleplay-create', kwargs={
            'training_uuid': cls.training.id
        })

        first_step = cls.roleplay.steps.first()
        first_criterion = first_step.criteria.first()

        cls.roleplay_urls = [
            cls.roleplay_create_url,
            cls.roleplay.get_edit_url(),
            cls.roleplay.get_delete_url(),
            cls.roleplay.get_step_create_url(),
            cls.roleplay.get_steps_sort_url(),
            first_step.get_edit_url(),
            first_step.get_delete_url(),
            first_step.get_criterion_create_url(),
            first_step.get_criteria_sort_url(),
            first_criterion.get_edit_url(),
            first_criterion.get_delete_url()
        ]

        # Some urls may return a 404 if the training is not editable
        cls.training.version_state = cls.training.VERSION_STATES.DRAFT
        cls.training.save()

    def test_roleplay_view_response_as_trainee(self):
        """Test the roleplay ``roleplay-create`` view as a trainee.

        Since the user is a trainee, and the roleplays app url are only
        available to the superusers or trainer, the trainee should be
        redirected to the login page of the cms.

        """

        self.login_as_trainee()

        for url in self.roleplay_urls:
            with self.subTest(url=url):
                response = self.client.get(url)

                # The trainee should be redirected
                self.assertEqual(response.status_code, 302)

    def test_roleplay_view_response_as_trainer(self):
        """Test the roleplay ``roleplay-create`` view as a trainer."""

        self.login_as_trainer()

        for url in self.roleplay_urls:
            with self.subTest(url=url):
                response = self.client.get(url)
                # The trainer should'nt be redirected
                self.assertEqual(response.status_code, 200)


class TestCriterionDimension(MTPSimpleAssessmentTestCase):
    """Test case that tests the ``Criterion`` views."""

    def test_with_dimensions(self):
        """ Test the creation of criteria with dimensions. """

        roleplay = RoleplayFactory(training=self.training)
        self.training.version_state = self.training.VERSION_STATES.DRAFT
        self.training.save()
        roleplay.is_assessing = True
        roleplay.save()
        roleplay_step = StepFactory.create(roleplay=roleplay)

        url = roleplay_step.get_criterion_create_url()
        self.login_as_trainer()

        response = self.client.post(url, data={"name": "no_dimensions",
                                               "criterion_type": "QT"})

        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            roleplay_step.criteria.get(name="no_dimensions").dimensions.count(),
            0
        )
        response = self.client.post(
            url,
            data={
                "name": "with_dimensions",
                "criterion_type": "QT",
                "dimensions": [self.dimensions[0].id]
            }
        )

        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            roleplay_step.criteria.get(name="with_dimensions").dimensions.count(),
            1
        )


class XLSImportViewTestCase(MTPTestCase):
    """ Test case that tests the ``XLSImportView`` class. """

    @classmethod
    def setUpTestData(cls):
        super().setUpTestData()

        # Create dimension
        tree = CompetencyTreeFactory()
        competency = CompetencyFactory(tree=tree)
        DimensionFactory(code='DIM1', competency=competency)
        DimensionFactory(code='DIM2', competency=competency)

        file_path = os.path.join(settings.APPS_ROOT, 'import_export/xls_test_files/roleplay.xlsx')
        cls.file = open(file_path, 'rb')

        cls.roleplay_data = {'name': 'test_roleplay_import'}

        with cls.training.override_version_state(cls.training.VERSION_STATES.DRAFT):
            cls.training.version_state = cls.training.VERSION_STATES.DRAFT
            cls.training.job_profile = tree.job_profile
            cls.training.save()

    def test_creation_roleplay_with_import_file(self):
        """ Test the creation of roleplay with import file. """
        url = reverse('roleplays:import-xls', kwargs={'training_uuid': self.training.id})
        self.login_as_trainer()

        data = {'file': self.file, 'is_assessing': True}
        self.client.post(url, data=data, follow=True)

        # Test imported object exists
        queryset = Roleplay.objects.filter(**self.roleplay_data)
        self.assertTrue(queryset.exists())

        # We check imported object contains 1 step et 5 criteria.
        created_roleplay = queryset.first()
        self.assertEqual(created_roleplay.steps.count(), 1)
        self.assertEqual(
            len(Criterion.objects.filter(step__roleplay=created_roleplay)),
            5
        )

        # We check dimensions are related
        criterion_1 = Criterion.objects.get(name='Warm welcome')
        self.assertEqual(criterion_1.dimensions.count(), 2)
        criterion_2 = Criterion.objects.get(name='Warm welcome2')
        self.assertEqual(criterion_2.dimensions.count(), 1)
