"""Base test cases for testing trainings."""

from mtp.apps.accounts.factories import (
    GroupRoleFactory,
    GroupFactory,
    TrainerFactory
)
from mtp.apps.accounts.models import GroupRole
from mtp.apps.brainstormers.tests.test_cases import (
    BaseBrainstormerActivityTestCase, BaseBrainstormerTestCase
)
from mtp.apps.common.tests.test_cases import MTPTestCase, DEFAULT_PASSWORD
from mtp.apps.documents.tests.test_cases import BaseDocumentTestCase
from mtp.apps.evaluations.tests.test_cases import BaseEvaluationTestCase
from mtp.apps.metaplans.tests.test_cases import BaseMetaplanTestCase
from mtp.apps.roleplays.tests.test_cases import BaseRoleplayTestCase
from mtp.apps.trainings.models import Training
from mtp.apps.workshops.tests.test_cases import BaseWorkshopTestCase


class BaseTrainingTestCase(MTPTestCase):
    """Base test case to tests trainings.

    It provides some default test data useful in a lot of tests.

    """

    @classmethod
    def setUpTestData(cls):
        """Create some data to use in trainings tests."""

        super().setUpTestData()

        # New trainer
        cls.new_trainer = TrainerFactory(password=DEFAULT_PASSWORD)

        # The trainer is a member of the business unit
        GroupRoleFactory(user=cls.new_trainer, group=cls.business_unit)

        # We got another trainer, member of the base business unit,
        # but also manager of another one
        cls.trainer_manager = TrainerFactory()
        GroupRoleFactory(user=cls.trainer_manager, group=cls.business_unit)
        cls.business_unit_2 = GroupFactory()
        GroupRoleFactory(user=cls.trainer_manager, group=cls.business_unit_2,
                         role=GroupRole.ROLES.MANAGER)

    def setUp(self):
        """Reload the training from the database to clear cache..."""

        super().setUp()

        self.training = Training.objects.get(pk=self.training.pk)

    def tearDown(self):
        """Reset the redis locks fields."""

        for instance in self.training.redis_model.collection().instances():
            instance.duplicate_to_member_locks.delete()
            instance.create_draft_locks.delete()

        super().tearDown()

    def check_training(self, training, attributes_to_check, activities_count=None):
        """Simple helper to check that a training has the wanted attributes.

        Parameters
        ----------
        training : Training
            The training to test
        attributes_to_check : dict
            For each entry in this dict we'll check that the field defined by the key has the
            correct value defined by the value.
        activities_count : integer, optional
            If set, the number of activities we expect the training to have

        """

        # Check each attribute
        for attribute, value in attributes_to_check.items():
            with self.subTest(attribute=attribute):
                self.assertEqual(
                    getattr(training, attribute),
                    value
                )

        # Check the number of activities
        if activities_count is not None:
            with self.subTest(attribute='activities_count'):
                self.assertEqual(
                    training.activities.count(),
                    activities_count
                )


class TrainingWithActivitiesTestCase(BaseWorkshopTestCase, BaseRoleplayTestCase,
                                     BaseEvaluationTestCase, BaseDocumentTestCase,
                                     BaseBrainstormerTestCase, BaseMetaplanTestCase,
                                     BaseTrainingTestCase, BaseBrainstormerActivityTestCase):
    """A test case to use when testing a training with activities

    Each parent adds a ``TrainingActivity`` children instance in the context
    accordingly to the app it's coming from:

    - ``BaseWorkshopTestCase`` : ``mtp.apps.workshops.models.Workshop`` instance.
    - ``BaseRoleplayTestCase`` : ``mtp.apps.roleplays.models.Roleplay`` instance.
    - ``BaseEvaluationTestCase`` : ``mtp.apps.evaluations.models.Evaluation`` instance.
    - ``BaseDocumentTestCase`` : ``mtp.apps.documents.models.Document`` instance.
    - ``BaseBrainstormerTestCase`` : ``mtp.apps.brainstormers.models.BrainstormerTemplate``
    instance.
    - ``BaseBrainstormerActivityTestCase`` : ``mtp.apps.brainstormers.models.BrainstormerActivity``
    instance.
    - ``BaseMetaplanTestCase`` : ``mtp.apps.metaplans.models.MetaplanTemplate`` instance.

    """
