"""Test cases for the ``workshops`` forms."""

import io

from PIL import Image

from django.core.files.uploadedfile import SimpleUploadedFile

from mtp.apps.assessments.tests.test_cases import MTPSimpleAssessmentTestCase
from mtp.apps.common.tests.waffle_test_utils import override_switch
from mtp.apps.workshops.factories import WorkshopFactory
from mtp.apps.workshops.tests.test_cases import WorkshopTestCase

from ..forms import (
    WorkshopAssessableForm,
    WorkshopForm,
    WorkshopStepImageForm,
    WorkshopStepQuestionAssessableForm,
    WorkshopStepQuestionForm,
)


class WorkshopStepQuestionFormTestCase(MTPSimpleAssessmentTestCase, WorkshopTestCase):
    """Test case that tests the ``WorkshopStepQuestionForm`` form."""

    def test_is_valid(self):
        """Test the `is_valid` method."""

        form = WorkshopStepQuestionForm(
            data={
                'title': 'title_test',
                'is_multiple_choices': False,
                'is_all_or_nothing': True,
            },
            workshop=self.workshop
        )
        self.assertFalse(form.is_valid())
        self.assertTrue(form.has_error('is_all_or_nothing'))

        form = WorkshopStepQuestionForm(
            data={
                'title': 'title_test',
                'is_multiple_choices': True,
                'is_all_or_nothing': True,
            }
        )
        self.assertTrue(form.is_valid())
        self.assertFalse(form.has_error('is_all_or_nothing'))

    @override_switch('enable_assessments', active=True)
    def test_with_assessment(self):
        """Test ``WorkshopStepQuestionAssessableForm`` with assessment."""

        self.workshop = WorkshopFactory(training=self.training, is_assessing=True)

        form = WorkshopStepQuestionAssessableForm(
            data={
                'title': 'title_test',
                'dimensions': [self.dimensions[0].id],
            },
            training=self.training,
            activity=self.workshop_question,
            workshop=self.workshop,
        )

        # Assessment is enabled, these fields should be available
        self.assertIn('dimensions', form.fields)

        # The form should be valid
        self.assertTrue(form.is_valid())

        # The form should create/update the wanted object
        with self.training.override_version_state(self.training.VERSION_STATES.DRAFT):
            assessable_object = form.save()
            self.assertTrue(assessable_object.is_assessing)
            self.assertEqual(self.workshop, assessable_object.workshop)
            self.assertIn(self.dimensions[0], assessable_object.dimensions.all())

    @override_switch('enable_assessments', active=False)
    def test_without_assessment(self):
        """Test ``WorkshopStepQuestionForm`` without assessment."""

        form = WorkshopStepQuestionForm(
            data={
                'title': 'title_test',
            },
            workshop=self.workshop,
        )

        # Assessment is disabled, these fields should'nt be available
        self.assertNotIn('is_assessing', form.fields)
        self.assertNotIn('dimensions', form.fields)

        # The form should be valid
        self.assertTrue(form.is_valid())

        # The form should create/update the wanted object
        assessable_object = form.save(commit=False)
        self.assertEqual(self.workshop, assessable_object.workshop)


class WorkshopFormTestCase(WorkshopTestCase):
    """Test case that tests the ``WorkshopForm`` form."""

    @override_switch('enable_assessments', active=True)
    def test_with_assessment(self):
        """Test ``WorkshopAssessableForm`` with assessment."""

        form = WorkshopAssessableForm(
            data={
                'name': 'fake_name',
                'description': 'fake_description',
                'is_assessing': True,
            }
        )

        # Assessment is enabled, this field should be available
        self.assertIn('is_assessing', form.fields)

        # The form should be valid
        self.assertTrue(form.is_valid())

        # The form should create/update the wanted object
        assessable_object = form.save(commit=False)
        self.assertTrue(assessable_object.is_assessing)

    @override_switch('enable_assessments', active=False)
    def test_without_assessment(self):
        """Test ``WorkshopForm`` without assessment."""

        form = WorkshopForm(
            data={
                'name': 'fake_name',
                'description': 'fake_description',
            }
        )

        # Assessment is disabled, this field shouldn't be available
        self.assertNotIn('is_assessing', form.fields)

        # The form should be valid
        self.assertTrue(form.is_valid())

        # The form should create/update the wanted object
        assessable_object = form.save(commit=False)
        self.assertIsNotNone(assessable_object)


class WorkshopStepImageFormTestCase(WorkshopTestCase):
    """Test case that tests the ``WorkshopStepImageForm`` form."""

    @staticmethod
    def get_image():
        """Create an image to upload in the form."""

        image = Image.new(mode='RGB', size=(200, 200))
        image_io = io.BytesIO()
        image.save(image_io, 'jpeg')

        return SimpleUploadedFile(
            name='fake.png',
            content=image_io.getvalue(),
            content_type='image/png',
        )

    def test_is_valid(self):
        """Test the ``is_valid`` method."""

        form = WorkshopStepImageForm(
            data={
                'title': 'fake_name',
            },
            files={
                'image': self.get_image(),
            },
            workshop=self.workshop,
        )

        # The form should be valid
        self.assertTrue(form.is_valid())

        # The form should create/update the wanted object
        obj = form.save(commit=False)
        self.assertEqual(obj.title, 'fake_name')
        self.assertEqual(obj.image.name, 'fake.png')
