"""
Tests pour l'application Universities
"""
from django.test import TestCase, Client
from django.urls import reverse
from decimal import Decimal
import json

from .models import University, UniversityDepartment, UniversityStatistic, IndustrialPartner
from config.models import Country
from apps.core.models import UniversityMapSettings


class UniversityModelTest(TestCase):
    """Tests pour le modèle University"""

    def setUp(self):
        self.country = Country.objects.create(
            name="France",
            code="FR"
        )
        self.university = University.objects.create(
            name="Université Paris-Saclay",
            country=self.country,
            city="Gif-sur-Yvette",
            description="Leading research university in France",
            latitude=Decimal('48.709700'),
            longitude=Decimal('2.165400'),
            is_coordinator=True,
            is_active=True
        )

    def test_university_creation(self):
        """Test création d'une université"""
        self.assertEqual(self.university.name, "Université Paris-Saclay")
        self.assertEqual(self.university.city, "Gif-sur-Yvette")
        self.assertTrue(self.university.is_coordinator)

    def test_str_representation(self):
        """Test de la représentation string"""
        self.assertEqual(str(self.university), "Université Paris-Saclay")

    def test_slug_auto_generation(self):
        """Test génération automatique du slug"""
        self.assertEqual(self.university.slug, "universite-paris-saclay")

    def test_coordinates(self):
        """Test des coordonnées géographiques"""
        self.assertEqual(self.university.latitude, Decimal('48.709700'))
        self.assertEqual(self.university.longitude, Decimal('2.165400'))

    def test_ordering(self):
        """Test de l'ordre des universités"""
        uni2 = University.objects.create(
            name="Uni B",
            country=self.country,
            city="Paris",
            description="Test",
            order=0
        )
        universities = list(University.objects.all())
        self.assertEqual(universities[0], uni2)  # order=0


class UniversityDepartmentModelTest(TestCase):
    """Tests pour le modèle UniversityDepartment"""

    def setUp(self):
        self.country = Country.objects.create(name="Germany", code="DE")
        self.university = University.objects.create(
            name="TU Munich",
            country=self.country,
            city="Munich",
            description="Technical University"
        )
        self.department = UniversityDepartment.objects.create(
            university=self.university,
            name="Computer Science Department",
            specialization="AI and Machine Learning"
        )

    def test_department_creation(self):
        """Test création d'un département"""
        self.assertEqual(self.department.name, "Computer Science Department")
        self.assertEqual(self.department.university, self.university)

    def test_str_representation(self):
        """Test de la représentation string"""
        self.assertIn("Computer Science", str(self.department))


class UniversityStatisticModelTest(TestCase):
    """Tests pour le modèle UniversityStatistic"""

    def setUp(self):
        self.country = Country.objects.create(name="Italy", code="IT")
        self.university = University.objects.create(
            name="Politecnico di Milano",
            country=self.country,
            city="Milan",
            description="Technical University"
        )
        self.stat = UniversityStatistic.objects.create(
            university=self.university,
            stat_type='students',
            value=45000,
            year=2024
        )

    def test_statistic_creation(self):
        """Test création d'une statistique"""
        self.assertEqual(self.stat.value, 45000)
        self.assertEqual(self.stat.stat_type, 'students')

    def test_unique_together(self):
        """Test contrainte d'unicité"""
        from django.db import IntegrityError
        with self.assertRaises(IntegrityError):
            UniversityStatistic.objects.create(
                university=self.university,
                stat_type='students',
                value=50000,
                year=2024
            )


class UniversityListViewTest(TestCase):
    """Tests pour la vue liste des universités"""

    def setUp(self):
        self.client = Client()
        self.country = Country.objects.create(name="France", code="FR")
        self.university = University.objects.create(
            name="Test University",
            country=self.country,
            city="Paris",
            description="Test description",
            is_active=True,
            latitude=Decimal('48.8566'),
            longitude=Decimal('2.3522')
        )

    def test_list_view_status_code(self):
        """Test que la page liste retourne 200"""
        response = self.client.get(reverse('universities:list'))
        self.assertEqual(response.status_code, 200)

    def test_list_view_template(self):
        """Test du template utilisé"""
        response = self.client.get(reverse('universities:list'))
        self.assertTemplateUsed(response, 'universities/list.html')

    def test_list_view_context(self):
        """Test du contexte de la vue"""
        response = self.client.get(reverse('universities:list'))
        self.assertIn('universities', response.context)
        self.assertIn('map_settings', response.context)

    def test_inactive_universities_not_shown(self):
        """Test que les universités inactives ne sont pas affichées"""
        University.objects.create(
            name="Inactive Uni",
            country=self.country,
            city="Paris",
            description="Test",
            is_active=False
        )
        response = self.client.get(reverse('universities:list'))
        self.assertEqual(response.context['universities'].count(), 1)


class UniversityDetailViewTest(TestCase):
    """Tests pour la vue détail d'une université"""

    def setUp(self):
        self.client = Client()
        self.country = Country.objects.create(name="France", code="FR")
        self.university = University.objects.create(
            name="Test University",
            country=self.country,
            city="Paris",
            description="Test description",
            is_active=True
        )

    def test_detail_view_status_code(self):
        """Test que la page détail retourne 200"""
        response = self.client.get(
            reverse('universities:detail', kwargs={'slug': self.university.slug})
        )
        self.assertEqual(response.status_code, 200)

    def test_detail_view_template(self):
        """Test du template utilisé"""
        response = self.client.get(
            reverse('universities:detail', kwargs={'slug': self.university.slug})
        )
        self.assertTemplateUsed(response, 'universities/detail.html')

    def test_detail_view_404_for_inactive(self):
        """Test 404 pour université inactive"""
        self.university.is_active = False
        self.university.save()
        response = self.client.get(
            reverse('universities:detail', kwargs={'slug': self.university.slug})
        )
        self.assertEqual(response.status_code, 404)


class UniversityMapDataViewTest(TestCase):
    """Tests pour l'API de données de la carte"""

    def setUp(self):
        self.client = Client()
        self.country = Country.objects.create(name="France", code="FR")
        self.university = University.objects.create(
            name="Test University",
            country=self.country,
            city="Paris",
            description="Test description",
            latitude=Decimal('48.8566'),
            longitude=Decimal('2.3522'),
            is_active=True
        )
        # Créer les paramètres de carte
        UniversityMapSettings.get_settings()

    def test_map_data_returns_json(self):
        """Test que l'API retourne du JSON"""
        response = self.client.get(reverse('universities:map_data'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['Content-Type'], 'application/json')

    def test_map_data_structure(self):
        """Test de la structure des données"""
        response = self.client.get(reverse('universities:map_data'))
        data = json.loads(response.content)

        self.assertIn('universities', data)
        self.assertIn('settings', data)
        self.assertEqual(len(data['universities']), 1)

    def test_map_data_university_fields(self):
        """Test des champs d'une université dans les données"""
        response = self.client.get(reverse('universities:map_data'))
        data = json.loads(response.content)

        uni = data['universities'][0]
        self.assertIn('id', uni)
        self.assertIn('name', uni)
        self.assertIn('latitude', uni)
        self.assertIn('longitude', uni)
        self.assertIn('is_coordinator', uni)
        self.assertIn('url', uni)

    def test_map_data_excludes_universities_without_coordinates(self):
        """Test que les universités sans coordonnées sont exclues"""
        University.objects.create(
            name="No Coords Uni",
            country=self.country,
            city="Lyon",
            description="Test",
            is_active=True
            # Pas de latitude/longitude
        )
        response = self.client.get(reverse('universities:map_data'))
        data = json.loads(response.content)

        self.assertEqual(len(data['universities']), 1)

    def test_map_data_settings(self):
        """Test des paramètres de carte dans les données"""
        response = self.client.get(reverse('universities:map_data'))
        data = json.loads(response.content)

        settings = data['settings']
        self.assertIn('tile_url', settings)
        self.assertIn('attribution', settings)
        self.assertIn('center', settings)
        self.assertIn('zoom', settings)
        self.assertIn('marker_color', settings)
