import os
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_ckeditor_5.fields import CKEditor5Field
from django.utils.html import format_html
from traduction.helpers import TranslatableMixin


class Orderable(models.Model):
    """
    Abstract model for handling orderable objects.

    Fournit:
    - Champ order pour le tri
    - Methode save_order() pour auto-incrementer
    - Methode de classe resequence_all() pour reinitialiser l'ordre
    """
    order = models.PositiveSmallIntegerField(default=0, verbose_name=_("Order"))

    class Meta:
        abstract = True
        ordering = ['order']

    def save_order(self):
        """Auto-incremente l'ordre pour les nouveaux objets."""
        if not self.pk:
            max_order = self.__class__.objects.all().aggregate(
                max_order=models.Max('order')
            )['max_order']
            self.order = 1 if max_order is None else max_order + 1

    @classmethod
    def resequence_all(cls, queryset=None, filter_kwargs=None):
        """
        Reinitialise l'ordre de tous les elements (1, 2, 3...).

        Args:
            queryset: QuerySet optionnel a reordonner
            filter_kwargs: Dict de filtres optionnels (ex: {'page_id': 1})

        Returns:
            Tuple (total, updated) - nombre total et mis a jour
        """
        if queryset is None:
            queryset = cls.objects.all()

        if filter_kwargs:
            queryset = queryset.filter(**filter_kwargs)

        items = list(queryset.order_by('order', 'pk'))
        updated = 0

        for index, item in enumerate(items, start=1):
            if item.order != index:
                item.order = index
                item.save(update_fields=['order'])
                updated += 1

        return len(items), updated

    @classmethod
    def get_next_order(cls, filter_kwargs=None):
        """Retourne le prochain numero d'ordre disponible."""
        queryset = cls.objects.all()
        if filter_kwargs:
            queryset = queryset.filter(**filter_kwargs)

        max_order = queryset.aggregate(max_order=models.Max('order'))['max_order']
        return 1 if max_order is None else max_order + 1


class Timestamped(models.Model):
    """
    Abstract model for handling created_at and updated_at timestamps
    """
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class ContentAble(models.Model):
    """
    Abstract model for handling created_at and updated_at timestamps
    """
    content = models.TextField(blank=True, verbose_name=_("Content"))

    class Meta:
        abstract = True

    def contenu_100(self):
        return self.content[:100]


class Activatable(models.Model):
    """
    Abstract model for handling active field
    """
    active = models.BooleanField(default=True, verbose_name=_("Active"))

    class Meta:
        abstract = True


class HtmlFieldSet(models.Model):
    """
    Abstract model for handling WYSIWYG content field
    """
    content = CKEditor5Field(blank=True, verbose_name=_("Content"), config_name='extends')

    class Meta:
        abstract = True


class Genre(TranslatableMixin, Timestamped):
    libelle = models.CharField(max_length=32, verbose_name=_("Libelle"))

    def __str__(self):
        return self.get_translated('libelle') or self.libelle


class Icongroup(models.Model):
    libelle = models.CharField(max_length=16, verbose_name=_("Libelle"))

    def __str__(self):
        return self.libelle


class Icon(TranslatableMixin, models.Model):
    group = models.ForeignKey(
        Icongroup,
        related_name='icongroup',
        on_delete=models.RESTRICT,
        verbose_name=_("Group"),
    )
    libelle = models.CharField(max_length=32, verbose_name=_("Libelle"))

    def __str__(self):
        return self.get_translated('libelle') or self.libelle

    def icon_tag(self):
        return format_html('<div class="icon"><i class="{} {}"></i></div>', self.group.libelle, self.libelle)



class Country(TranslatableMixin, models.Model):
    name = models.CharField(max_length=100, unique=True)  # Nom complet du pays
    code = models.CharField(max_length=2, unique=True)   # Code ISO Alpha-2 (ex : "FR" pour France)
    alpha_3 = models.CharField(max_length=3, unique=True, null=True, blank=True)  # Code ISO Alpha-3 (ex : "FRA")
    numeric = models.CharField(max_length=3, unique=True, null=True, blank=True) # Code numérique ISO
    official_name = models.CharField(max_length=150, null=True, blank=True)  # Nom officiel complet du pays

    def __str__(self):
        return self.get_translated('name') or self.name


class StatType(TranslatableMixin, Orderable):
    """
    Types de statistiques pour les universites.

    Exemples: Enseignants, Etudiants, Doctorants, Laboratoires, Publications/an
    """
    code = models.CharField(
        'Code',
        max_length=30,
        unique=True,
        help_text='Identifiant unique (ex: faculty, students)'
    )
    name = models.CharField('Nom', max_length=100)
    icon = models.ForeignKey(
        Icon,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name='Icone',
        related_name='stat_types'
    )
    is_active = models.BooleanField('Actif', default=True)

    class Meta:
        verbose_name = 'Type de statistique'
        verbose_name_plural = 'Types de statistiques'
        ordering = ['order', 'name']

    def __str__(self):
        return self.get_translated('name') or self.name

    def save(self, *args, **kwargs):
        self.save_order()
        super().save(*args, **kwargs)

