"""This module holds the test cases related to the views of the ``ideas`` app"""

import json

from ..models import (
    Brainstorming,
    QuestionWall,
    WordCloud,
)

from .test_cases import IdeasTestCase


class BrainstormingViewsTestCase(IdeasTestCase):
    """Test case for the ``Brainstorming`` related views"""

    @classmethod
    def setUpTestData(cls):
        """The training must be editable to edit/add the activities"""

        super().setUpTestData()

        cls.urls_to_test = [
            Brainstorming.get_training_create_url(cls.training),
            cls.brainstorming.get_edit_url(),
            cls.brainstorming.get_delete_url(),
        ]

        cls.training.version_state = cls.training.VERSION_STATES.DRAFT
        cls.training.save()

    def test_non_training_owner_should_not_have_access(self):
        """Test that users who don't own the training should not be allowed to access the views"""

        self.login_as_admin()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 404)

    def test_training_owner_should_have_access(self):
        """Test that users who own the training should be allowed to access the views"""

        self.login_as_trainer()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 200)

    def test_create_brainstorming_view_should_work_with_training(self):
        """Test creating a new ``Brainstorming`` instance with the ``BrainstormingCreateView``"""

        # We have only one brainstorming
        self.assertEqual(Brainstorming.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            Brainstorming.get_training_create_url(self.training),
            {
                'name': 'New brainstorming',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two brainstorming
        self.assertEqual(Brainstorming.objects.count(), 2)

        new_brainstorming = Brainstorming.objects.get(name='New brainstorming')
        self.assertEqual(new_brainstorming.description, 'Description')
        self.assertTrue(new_brainstorming.is_anonymous)

    def test_create_brainstorming_view_should_work(self):
        """Test creating a new ``Brainstorming`` instance with the ``BrainstormingCreateView``"""

        # We have only one brainstorming
        self.assertEqual(Brainstorming.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            Brainstorming.get_create_url(),
            {
                'name': 'New brainstorming',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid and that we have the correct redirect url
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two brainstorming
        self.assertEqual(Brainstorming.objects.count(), 2)

        new_brainstorming = Brainstorming.objects.get(name='New brainstorming')
        self.assertEqual(new_brainstorming.description, 'Description')
        self.assertTrue(new_brainstorming.is_anonymous)

    def test_update_brainstorming_view_should_work(self):
        """Test updating a ``Brainstorming`` instance with the ``BrainstormingUpdateView``"""

        self.login_as_trainer()

        old_name = self.brainstorming.name

        response = self.client.post(
            self.brainstorming.get_edit_url(),
            {
                'name': 'Updated name'
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        self.brainstorming.refresh_from_db()
        self.assertNotEqual(self.brainstorming.name, old_name)
        self.assertEqual(self.brainstorming.name, 'Updated name')


class QuestionWallViewsTestCase(IdeasTestCase):
    """Test case for the ``QuestionWall`` related views"""

    @classmethod
    def setUpTestData(cls):
        """The training must be editable to edit/add the activities"""

        super().setUpTestData()

        cls.urls_to_test = [
            QuestionWall.get_training_create_url(cls.training),
            cls.questionwall.get_edit_url(),
            cls.questionwall.get_delete_url(),
        ]

        cls.training.version_state = cls.training.VERSION_STATES.DRAFT
        cls.training.save()

    def test_non_training_owner_should_not_have_access(self):
        """Test that users who don't own the training should not be allowed to access the views"""

        self.login_as_admin()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 404)

    def test_training_owner_should_have_access(self):
        """Test that users who own the training should be allowed to access the views"""

        self.login_as_trainer()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 200)

    def test_create_questionwall_view_should_work_with_training(self):
        """Test creating a new ``QuestionWall`` instance with the ``QuestionWallCreateView``"""

        # We have only one questionwall
        self.assertEqual(QuestionWall.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            QuestionWall.get_training_create_url(self.training),
            {
                'name': 'New questionwall',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two questionwall
        self.assertEqual(QuestionWall.objects.count(), 2)

        new_questionwall = QuestionWall.objects.get(name='New questionwall')
        self.assertEqual(new_questionwall.description, 'Description')
        self.assertTrue(new_questionwall.is_anonymous)

    def test_create_questionwall_view_should_work(self):
        """Test creating a new ``QuestionWall`` instance with the ``QuestionWallCreateView``"""

        # We have only one questionwall
        self.assertEqual(QuestionWall.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            QuestionWall.get_create_url(),
            {
                'name': 'New questionwall',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two questionwall
        self.assertEqual(QuestionWall.objects.count(), 2)

        new_questionwall = QuestionWall.objects.get(name='New questionwall')
        self.assertEqual(new_questionwall.description, 'Description')
        self.assertTrue(new_questionwall.is_anonymous)

    def test_update_questionwall_view_should_work(self):
        """Test updating a ``QuestionWall`` instance with the ``QuestionWallUpdateView``"""

        self.login_as_trainer()

        old_name = self.questionwall.name

        response = self.client.post(
            self.questionwall.get_edit_url(),
            {
                'name': 'Updated name'
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        self.questionwall.refresh_from_db()
        self.assertNotEqual(self.questionwall.name, old_name)
        self.assertEqual(self.questionwall.name, 'Updated name')


class WordCloudViewsTestCase(IdeasTestCase):
    """Test case for the ``WordCloud`` related views"""

    @classmethod
    def setUpTestData(cls):
        """The training must be editable to edit/add the activities"""

        super().setUpTestData()

        cls.urls_to_test = [
            WordCloud.get_training_create_url(cls.training),
            cls.wordcloud.get_edit_url(),
            cls.wordcloud.get_delete_url(),
        ]

        cls.training.version_state = cls.training.VERSION_STATES.DRAFT
        cls.training.save()

    def test_non_training_owner_should_not_have_access(self):
        """Test that users who don't own the training should not be allowed to access the views"""

        self.login_as_admin()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 404)

    def test_training_owner_should_have_access(self):
        """Test that users who own the training should be allowed to access the views"""

        self.login_as_trainer()

        for url in self.urls_to_test:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 200)

    def test_create_wordcloud_view_should_work_with_training(self):
        """Test creating a new ``WordCloud`` instance with the ``WordCloudCreateView``"""

        # We have only one wordcloud
        self.assertEqual(WordCloud.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            WordCloud.get_training_create_url(self.training),
            {
                'name': 'New wordcloud',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two wordcloud
        self.assertEqual(WordCloud.objects.count(), 2)

        new_wordcloud = WordCloud.objects.get(name='New wordcloud')
        self.assertEqual(new_wordcloud.description, 'Description')
        self.assertTrue(new_wordcloud.is_anonymous)

    def test_create_wordcloud_view_should_work(self):
        """Test creating a new ``WordCloud`` instance with the ``WordCloudCreateView``"""

        # We have only one wordcloud
        self.assertEqual(WordCloud.objects.count(), 1)

        self.login_as_trainer()

        response = self.client.post(
            WordCloud.get_create_url(),
            {
                'name': 'New wordcloud',
                'description': 'Description',
                'is_anonymous': True
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        # We have now two wordcloud
        self.assertEqual(WordCloud.objects.count(), 2)

        new_wordcloud = WordCloud.objects.get(name='New wordcloud')
        self.assertEqual(new_wordcloud.description, 'Description')
        self.assertTrue(new_wordcloud.is_anonymous)

    def test_update_questionwall_view_should_work(self):
        """Test updating a ``QuestionWall`` instance with the ``QuestionWallUpdateView``"""

        self.login_as_trainer()

        old_name = self.wordcloud.name

        response = self.client.post(
            self.wordcloud.get_edit_url(),
            {
                'name': 'Updated name'
            }
        )

        self.assertEqual(response.status_code, 200)

        # Check that the form is considered as valid
        json_content = json.loads(response.content.decode('utf-8'))
        self.assertTrue(json_content['valid'])

        self.wordcloud.refresh_from_db()
        self.assertNotEqual(self.wordcloud.name, old_name)
        self.assertEqual(self.wordcloud.name, 'Updated name')
