""" This module tests all our quiz models"""

import os
import shutil
import tempfile

from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.conf import settings
from .models import Sport, Criterion, CallToMove, KnowledgeSnack


class SportModelTest(TestCase):
    """Tests the sport model"""

    def setUp(self):
        self.name = "HIIT"
        self.url = (
            "https://www.buchsys.de/fu-berlin/angebote/aktueller_zeitraum/_HIIT_"
            "-_High_Intensity_Interval_Training___HOME.html "
        )

        self.test_sport = Sport(
            name=self.name,
            url=self.url,
        )

        self.test_sport.save()

    def test_sport_can_be_created(self):
        """New sport is written to the database"""
        test_sport = Sport.objects.first()
        self.assertEqual(test_sport.name, self.name)
        self.assertEqual(test_sport.url, self.url)


class CriterionRatingTest(TestCase):
    """Tests the Relation between Sport and Criterion"""

    def setUp(self):
        self.name = "HIIT"
        self.url = (
            "https://www.buchsys.de/fu-berlin/angebote/aktueller_zeitraum/_HIIT_"
            "-_High_Intensity_Interval_Training___HOME.html "
        )

        self.test_sport = Sport(
            name=self.name,
            url=self.url,
        )

        self.test_sport.save()

        self.criterion = Criterion(name="Einzelsport")
        self.criterion.save()

    def test_can_rate_criterion_for_sport(self):
        """A rating for a specific criterion can be added to a sport"""
        self.test_sport.rate(self.criterion, 10)
        self.assertEqual(self.test_sport.criteria_ratings.first(), self.criterion)
        self.assertEqual(self.test_sport.get_rating(self.criterion), 10)

    def test_rating_can_be_changed(self):
        """
        If a sport is rated again then the corresponding relation is changed,
        instead of recreated
        """
        first_rating_object = self.test_sport.rate(self.criterion, 10)
        second_rating_object = self.test_sport.rate(self.criterion, 8)
        self.assertEqual(first_rating_object, second_rating_object)
        self.assertEqual(self.test_sport.get_rating(criterion=self.criterion), 8)


class CriterionModelTest(TestCase):
    """Tests the Criterion model"""

    def test_criterion_can_be_created(self):
        """New criterion is saved to the db"""
        name = "Einzelsport"
        Criterion(name=name).save()
        test_criterion = Criterion.objects.first()
        self.assertEqual(test_criterion.name, name)


FIXTURE_IMAGES = os.path.join(settings.BASE_DIR, "quiz", "fixtures", "images")
MEDIA_ROOT = tempfile.mkdtemp(
    suffix="testing"
)  # Create a temp directory for files created during tests


@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class CallToMoveTest(TestCase):
    """Tests the Model for Call To Move"""

    def setUp(self):
        tempfile.mkdtemp(suffix="testing")  # recreate tmp folder before each test

        self.text = "Kreise deine Arme vor der nächsten Frage 3x nach hinten"
        self.image_name = "test_image.png"
        self.image_path = os.path.join(FIXTURE_IMAGES, self.image_name)
        self.image = SimpleUploadedFile(
            name=self.image_name,
            content=open(self.image_path, "rb").read(),
            content_type="image/png",
        )
        self.call_to_move = CallToMove(text=self.text, image=self.image)
        self.call_to_move.save()

    def tearDown(self) -> None:
        """Delete the temp dir after each test"""
        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)

    def test_can_create_call_to_move(self):
        """A call to move can be correctly created"""
        self.assertEqual(self.call_to_move.text, self.text)
        self.assertEqual(self.call_to_move.image.name, self.image.name)

    def test_can_save_and_load_call_to_move(self):
        """A saved Call to Move can be loaded"""
        call_to_move = CallToMove.objects.first()
        self.assertEqual(call_to_move.text, self.text)
        self.assertEqual(call_to_move.image.name, self.image.name)


@override_settings(MEDIA_ROOT=MEDIA_ROOT)
class KnowledgeSnackTest(TestCase):
    """Tests the Model for Knowledge Snack"""

    def setUp(self):
        tempfile.mkdtemp(suffix="testing")  # recreate tmp folder before each test

        self.text = "Dass Treppensteigen fast 5x so viele Kalorien verbrennt," \
                    "als bei der Nutzung des Aufzuges?"
        self.image_name = "test_image.png"
        self.image_path = os.path.join(FIXTURE_IMAGES, self.image_name)
        self.image = SimpleUploadedFile(
            name=self.image_name,
            content=open(self.image_path, "rb").read(),
            content_type="image/png",
        )
        self.knowledge_snack = KnowledgeSnack(text=self.text, image=self.image)
        self.knowledge_snack.save()

    def tearDown(self) -> None:
        """Delete the temp dir after each test"""
        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)

    def test_can_create_knowledge_snack(self):
        """A knowledge snack can be correctly created"""
        self.assertEqual(self.knowledge_snack.text, self.text)
        self.assertEqual(self.knowledge_snack.image.name, self.image.name)

    def test_can_save_and_load_call_to_move(self):
        """A saved Knowledge Snack can be loaded"""
        knowledge_snack = KnowledgeSnack.objects.first()
        self.assertEqual(knowledge_snack.text, self.text)
        self.assertEqual(knowledge_snack.image.name, self.image.name)