"""
Tests pour l'application Traduction
"""
from django.test import TestCase, Client, RequestFactory
from django.template import Template, Context
from django.contrib.contenttypes.models import ContentType

from .models import Language, Dictionnaire
from .middleware import LanguageMiddleware, set_language, get_current_language_code
from .helpers import get_translated_value, TranslatableMixin
from apps.core.models import CarouselSlide


class LanguageModelTest(TestCase):
    """Tests pour le modèle Language"""

    def test_language_creation(self):
        """Test création d'une langue"""
        lang = Language.objects.create(
            code='fr',
            name='Français',
            native_name='Français',
            is_default=True
        )
        self.assertEqual(lang.code, 'fr')
        self.assertTrue(lang.is_default)

    def test_str_representation(self):
        """Test de la représentation string"""
        lang = Language.objects.create(code='en', name='English')
        self.assertEqual(str(lang), 'English (en)')

    def test_only_one_default(self):
        """Test qu'une seule langue peut être par défaut"""
        lang1 = Language.objects.create(code='fr', name='Français', is_default=True)
        lang2 = Language.objects.create(code='en', name='English', is_default=True)

        lang1.refresh_from_db()
        self.assertFalse(lang1.is_default)
        self.assertTrue(lang2.is_default)

    def test_first_language_is_default(self):
        """Test que la première langue est automatiquement par défaut"""
        lang = Language.objects.create(code='fr', name='Français')
        self.assertTrue(lang.is_default)

    def test_get_default(self):
        """Test de la méthode get_default"""
        Language.objects.create(code='fr', name='Français', is_default=True, is_active=True)
        Language.objects.create(code='en', name='English', is_default=False, is_active=True)

        default = Language.get_default()
        self.assertEqual(default.code, 'fr')

    def test_get_active_languages(self):
        """Test de la méthode get_active_languages"""
        Language.objects.create(code='fr', name='Français', is_active=True, order=1)
        Language.objects.create(code='en', name='English', is_active=True, order=2)
        Language.objects.create(code='de', name='Deutsch', is_active=False, order=3)

        active = Language.get_active_languages()
        self.assertEqual(active.count(), 2)


class DictionnaireModelTest(TestCase):
    """Tests pour le modèle Dictionnaire"""

    def setUp(self):
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

        self.slide = CarouselSlide.objects.create(
            title='Bienvenue',
            subtitle='Sous-titre français'
        )

    def test_translation_creation(self):
        """Test création d'une traduction"""
        content_type = ContentType.objects.get_for_model(CarouselSlide)
        translation = Dictionnaire.objects.create(
            content_type=content_type,
            object_id=self.slide.id,
            field='title',
            language=self.lang_en,
            translation='Welcome'
        )
        self.assertEqual(translation.translation, 'Welcome')

    def test_str_representation(self):
        """Test de la représentation string"""
        content_type = ContentType.objects.get_for_model(CarouselSlide)
        translation = Dictionnaire.objects.create(
            content_type=content_type,
            object_id=self.slide.id,
            field='title',
            language=self.lang_en,
            translation='Welcome'
        )
        self.assertIn('title', str(translation))
        self.assertIn('en', str(translation))

    def test_unique_together(self):
        """Test contrainte d'unicité"""
        from django.db import IntegrityError
        content_type = ContentType.objects.get_for_model(CarouselSlide)

        Dictionnaire.objects.create(
            content_type=content_type,
            object_id=self.slide.id,
            field='title',
            language=self.lang_en,
            translation='Welcome'
        )

        with self.assertRaises(IntegrityError):
            Dictionnaire.objects.create(
                content_type=content_type,
                object_id=self.slide.id,
                field='title',
                language=self.lang_en,
                translation='Hello'
            )

    def test_get_translation(self):
        """Test de la méthode get_translation"""
        Dictionnaire.set_translation(self.slide, 'title', self.lang_en, 'Welcome')

        translation = Dictionnaire.get_translation(self.slide, 'title', 'en')
        self.assertEqual(translation, 'Welcome')

    def test_get_translation_returns_none_if_not_found(self):
        """Test que get_translation retourne None si pas de traduction"""
        translation = Dictionnaire.get_translation(self.slide, 'title', 'de')
        self.assertIsNone(translation)

    def test_set_translation(self):
        """Test de la méthode set_translation"""
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')

        translation = Dictionnaire.get_translation(self.slide, 'title', 'en')
        self.assertEqual(translation, 'Welcome')

    def test_set_translation_updates_existing(self):
        """Test que set_translation met à jour une traduction existante"""
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Hello')

        translation = Dictionnaire.get_translation(self.slide, 'title', 'en')
        self.assertEqual(translation, 'Hello')

    def test_get_translations_for_object(self):
        """Test de la méthode get_translations_for_object"""
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')
        Dictionnaire.set_translation(self.slide, 'subtitle', 'en', 'English subtitle')

        translations = Dictionnaire.get_translations_for_object(self.slide, 'en')
        self.assertEqual(translations.count(), 2)

    def test_delete_translations_for_object(self):
        """Test de la méthode delete_translations_for_object"""
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')
        Dictionnaire.set_translation(self.slide, 'subtitle', 'en', 'Subtitle')

        Dictionnaire.delete_translations_for_object(self.slide)

        translations = Dictionnaire.get_translations_for_object(self.slide)
        self.assertEqual(translations.count(), 0)


class TranslationHelperTest(TestCase):
    """Tests pour les helpers de traduction"""

    def setUp(self):
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

        self.slide = CarouselSlide.objects.create(
            title='Bienvenue',
            subtitle='Sous-titre'
        )
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')

    def test_get_translated_value_returns_translation(self):
        """Test que get_translated_value retourne la traduction"""
        value = get_translated_value(self.slide, 'title', language_code='en')
        self.assertEqual(value, 'Welcome')

    def test_get_translated_value_fallback_to_original(self):
        """Test fallback vers la valeur originale"""
        value = get_translated_value(self.slide, 'title', language_code='de', fallback=True)
        self.assertEqual(value, 'Bienvenue')

    def test_get_translated_value_no_fallback(self):
        """Test sans fallback"""
        value = get_translated_value(self.slide, 'title', language_code='de', fallback=False)
        self.assertIsNone(value)


class LanguageMiddlewareTest(TestCase):
    """Tests pour le middleware de langue"""

    def setUp(self):
        self.factory = RequestFactory()
        self.middleware = LanguageMiddleware(get_response=lambda r: r)
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

    def test_default_language_set(self):
        """Test que la langue par défaut est définie"""
        request = self.factory.get('/')
        request.session = {}
        self.middleware.process_request(request)

        self.assertEqual(request.current_language_code, 'fr')

    def test_language_from_get_parameter(self):
        """Test changement de langue via paramètre GET"""
        request = self.factory.get('/?lang=en')
        request.session = {}
        self.middleware.process_request(request)

        self.assertEqual(request.current_language_code, 'en')

    def test_language_persists_in_session(self):
        """Test que la langue persiste en session"""
        request = self.factory.get('/')
        request.session = {'current_language_code': 'en'}
        self.middleware.process_request(request)

        self.assertEqual(request.current_language_code, 'en')

    def test_invalid_language_ignored(self):
        """Test qu'une langue invalide est ignorée"""
        request = self.factory.get('/?lang=invalid')
        request.session = {}
        self.middleware.process_request(request)

        self.assertEqual(request.current_language_code, 'fr')


class TranslationTemplateTagsTest(TestCase):
    """Tests pour les template tags de traduction"""

    def setUp(self):
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

        self.slide = CarouselSlide.objects.create(
            title='Bienvenue',
            subtitle='Sous-titre'
        )
        Dictionnaire.set_translation(self.slide, 'title', 'en', 'Welcome')

    def test_translate_filter(self):
        """Test du filtre translate"""
        from django.utils import translation

        translation.activate('en')
        template = Template('{% load traduction_tags %}{{ slide|translate:"title" }}')
        context = Context({'slide': self.slide})
        result = template.render(context)

        self.assertEqual(result.strip(), 'Welcome')

    def test_trans_text_tag(self):
        """Test du tag trans_text"""
        from django.utils import translation

        translation.activate('en')
        template = Template("{% load traduction_tags %}{% trans_text 'Bonjour' 'Hello' 'Hallo' %}")
        context = Context({})
        result = template.render(context)

        self.assertEqual(result.strip(), 'Hello')

    def test_trans_text_tag_french(self):
        """Test du tag trans_text en français"""
        from django.utils import translation

        translation.activate('fr')
        template = Template("{% load traduction_tags %}{% trans_text 'Bonjour' 'Hello' 'Hallo' %}")
        context = Context({})
        result = template.render(context)

        self.assertEqual(result.strip(), 'Bonjour')


class SetLanguageUtilityTest(TestCase):
    """Tests pour la fonction set_language"""

    def setUp(self):
        self.factory = RequestFactory()
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

    def test_set_language_success(self):
        """Test changement de langue réussi"""
        request = self.factory.get('/')
        request.session = {}

        result = set_language(request, 'en')

        self.assertTrue(result)
        self.assertEqual(request.current_language_code, 'en')

    def test_set_language_invalid(self):
        """Test changement vers langue invalide"""
        request = self.factory.get('/')
        request.session = {}

        result = set_language(request, 'invalid')

        self.assertFalse(result)


class ExcerptAutoGenerationTest(TestCase):
    """Tests pour l'auto-generation de excerpt depuis content pour NewsArticle"""

    def setUp(self):
        self.lang_fr = Language.objects.create(code='fr', name='Français', is_default=True)
        self.lang_en = Language.objects.create(code='en', name='English')

        from apps.news.models import NewsArticle, NewsCategory
        self.category = NewsCategory.objects.create(
            name='Test Category',
            slug='test-category'
        )
        self.article = NewsArticle.objects.create(
            title='Test Article',
            content='<p>Contenu de test en français</p>',
            category=self.category
        )

    def test_excerpt_translation_auto_generated(self):
        """Test que la traduction de excerpt est auto-generee depuis content"""
        from apps.news.models import NewsArticle

        # Definir une traduction pour le contenu
        content_text = '<p>This is the English content for testing the auto-generation feature.</p>'
        Dictionnaire.set_translation(self.article, 'content', 'en', content_text)

        # Verifier que l'excerpt a ete auto-genere
        excerpt_translation = Dictionnaire.get_translation(self.article, 'excerpt', 'en')
        self.assertIsNotNone(excerpt_translation)
        self.assertEqual(excerpt_translation, 'This is the English content for testing the auto-generation feature.')

    def test_excerpt_translation_strips_html(self):
        """Test que les balises HTML sont supprimees de l'excerpt"""
        content_text = '<h1>Title</h1><p>Paragraph <strong>bold</strong> text</p>'
        Dictionnaire.set_translation(self.article, 'content', 'en', content_text)

        excerpt_translation = Dictionnaire.get_translation(self.article, 'excerpt', 'en')
        self.assertNotIn('<', excerpt_translation)
        self.assertNotIn('>', excerpt_translation)
        self.assertIn('Title', excerpt_translation)
        self.assertIn('bold', excerpt_translation)

    def test_excerpt_translation_max_150_chars(self):
        """Test que l'excerpt est limite a 150 caracteres"""
        content_text = '<p>' + 'A' * 200 + '</p>'
        Dictionnaire.set_translation(self.article, 'content', 'en', content_text)

        excerpt_translation = Dictionnaire.get_translation(self.article, 'excerpt', 'en')
        self.assertEqual(len(excerpt_translation), 150)

    def test_excerpt_translation_updated_when_content_updated(self):
        """Test que l'excerpt est mis a jour quand le content est mis a jour"""
        Dictionnaire.set_translation(self.article, 'content', 'en', '<p>First content</p>')
        Dictionnaire.set_translation(self.article, 'content', 'en', '<p>Updated content</p>')

        excerpt_translation = Dictionnaire.get_translation(self.article, 'excerpt', 'en')
        self.assertEqual(excerpt_translation, 'Updated content')
