from django.db import models
from django.utils.timezone import now
from django.conf import settings
from django.utils.translation import gettext_lazy as _

from School.models import SchoolClass, Fee, Discount, PaymentModeType, PaymentPlanType
from Auth.models import ProfileRole
from Establishment.models import Establishment

from datetime import datetime

import os

class Language(models.Model):
    """
    Représente une langue parlée par l’élève.
    """
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=200, default="")

    def __str__(self):
        return "LANGUAGE"

class Guardian(models.Model):
    """
    Représente un responsable légal (parent/tuteur) d’un élève.
    """
    last_name = models.CharField(max_length=200, default="")
    first_name = models.CharField(max_length=200, default="")
    birth_date = models.DateField(null=True, blank=True)
    address = models.CharField(max_length=200, default="", blank=True)
    phone = models.CharField(max_length=200, default="", blank=True)
    profession = models.CharField(max_length=200, default="", blank=True)
    profile_role = models.OneToOneField(ProfileRole, on_delete=models.CASCADE, related_name='guardian_profile', blank=True)

    def __str__(self):
        return self.last_name + "_" + self.first_name

class Sibling(models.Model):
    """
    Représente un frère ou une sœur d’un élève.
    """
    last_name = models.CharField(max_length=200, default="")
    first_name = models.CharField(max_length=200, default="")
    birth_date = models.DateField(null=True, blank=True)

    def __str__(self):
        return "SIBLING"

def registration_photo_upload_to(instance, filename):
    return f"registration_files/dossier_rf_{instance.pk}/parent/{filename}"

class Student(models.Model):
    """
    Représente l’élève inscrit ou en cours d’inscription.
    """
    class StudentGender(models.IntegerChoices):
        NONE = 0, _('Sélection du genre')
        MALE = 1, _('Garçon')
        FEMALE = 2, _('Fille')

    class StudentLevel(models.IntegerChoices):
        NONE = 0, _('Sélection du niveau')
        TPS = 1, _('TPS - Très Petite Section')
        PS = 2, _('PS - Petite Section')
        MS = 3, _('MS - Moyenne Section')
        GS = 4, _('GS - Grande Section')
        CP = 5, _('CP')
        CE1 = 6, _('CE1')
        CE2 = 7, _('CE2')
        CM1 = 8, _('CM1')
        CM2 = 9, _('CM2')

    photo = models.FileField(
        upload_to=registration_photo_upload_to,
        null=True,
        blank=True
    )
    last_name = models.CharField(max_length=200, default="")
    first_name = models.CharField(max_length=200, default="")
    gender = models.IntegerField(choices=StudentGender, default=StudentGender.NONE, blank=True)
    level = models.IntegerField(choices=StudentLevel, default=StudentLevel.NONE, blank=True)
    nationality = models.CharField(max_length=200, default="", blank=True)
    address = models.CharField(max_length=200, default="", blank=True)
    birth_date = models.DateField(null=True, blank=True)
    birth_place = models.CharField(max_length=200, default="", blank=True)
    birth_postal_code = models.IntegerField(default=0, blank=True)
    attending_physician = models.CharField(max_length=200, default="", blank=True)

    # Many-to-Many Relationship
    profiles = models.ManyToManyField('Auth.Profile', blank=True)

    # Many-to-Many Relationship
    guardians = models.ManyToManyField(Guardian, blank=True)

    # Many-to-Many Relationship
    siblings = models.ManyToManyField(Sibling, blank=True)

    # Many-to-Many Relationship
    registration_files = models.ManyToManyField('RegistrationSchoolFileTemplate', blank=True, related_name='students')

    # Many-to-Many Relationship
    spoken_languages = models.ManyToManyField(Language, blank=True)

    # One-to-Many Relationship
    associated_class = models.ForeignKey(SchoolClass, on_delete=models.SET_NULL, null=True, blank=True, related_name='students')

    def __str__(self):
        return self.last_name + "_" + self.first_name

    def getSpokenLanguages(self):
        """
        Retourne la liste des langues parlées par l’élève.
        """
        return self.spoken_languages.all()

    def getMainGuardian(self):
        """
        Retourne le responsable légal principal de l’élève.
        """
        return self.guardians.all()[0]

    def getGuardians(self):
        """
        Retourne tous les responsables légaux de l’élève.
        """
        return self.guardians.all()

    def getProfiles(self):
        """
        Retourne les profils utilisateurs liés à l’élève.
        """
        return self.profiles.all()

    def getSiblings(self):
        """
        Retourne les frères et sœurs de l’élève.
        """
        return self.siblings.all()

    def getNumberOfSiblings(self):
        """
        Retourne le nombre de frères et sœurs.
        """
        return self.siblings.count()

    @property
    def age(self):
        if self.birth_date:
            today = datetime.today()
            years = today.year - self.birth_date.year
            months = today.month - self.birth_date.month
            if today.day < self.birth_date.day:
                months -= 1
            if months < 0:
                years -= 1
                months += 12

            # Determine the age format
            if 6 <= months <= 12:
                return f"{years} years 1/2"
            else:
                return f"{years} years"
        return None

    @property
    def formatted_birth_date(self):
        if self.birth_date:
            return self.birth_date.strftime('%d-%m-%Y')
        return None

class RegistrationFileGroup(models.Model):
    name = models.CharField(max_length=255, default="")
    description = models.TextField(blank=True, null=True)
    establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='file_group', null=True, blank=True)

    def __str__(self):
        return self.name

    def __str__(self):
        return f'{self.group.name} - {self.id}'

def registration_file_path(instance, filename):
    # Génère le chemin : registration_files/dossier_rf_{student_id}/filename
    return f'registration_files/dossier_rf_{instance.student_id}/{filename}'

class RegistrationForm(models.Model):
    class RegistrationFormStatus(models.IntegerChoices):
        RF_IDLE = 0, _('Pas de dossier d\'inscription')
        RF_INITIALIZED = 1, _('Dossier d\'inscription initialisé')
        RF_SENT = 2, _('Dossier d\'inscription envoyé')
        RF_UNDER_REVIEW = 3, _('Dossier d\'inscription en cours de validation')
        RF_TO_BE_FOLLOWED_UP = 4, _('Dossier d\'inscription à relancer')
        RF_VALIDATED = 5, _('Dossier d\'inscription validé')
        RF_ARCHIVED = 6, _('Dossier d\'inscription archivé')
        RF_SEPA_SENT = 7, _('Mandat SEPA envoyé')
        RF_SEPA_TO_SEND = 8, _('Mandat SEPA à envoyer')

    # One-to-One Relationship
    student = models.OneToOneField(Student, on_delete=models.CASCADE, primary_key=True)
    status = models.IntegerField(choices=RegistrationFormStatus, default=RegistrationFormStatus.RF_IDLE)
    last_update = models.DateTimeField(auto_now=True)
    notes = models.CharField(max_length=200, blank=True)
    registration_link_code = models.CharField(max_length=200, default="", blank=True)
    registration_file = models.FileField(
        upload_to=registration_file_path,
        null=True,
        blank=True
    )
    sepa_file = models.FileField(
        upload_to=registration_file_path,
        null=True,
        blank=True
    )
    fusion_file = models.FileField(
        upload_to=registration_file_path,
        null=True,
        blank=True
    )
    associated_rf = models.CharField(max_length=200, default="", blank=True)

    # Many-to-Many Relationship
    fees = models.ManyToManyField(Fee, blank=True, related_name='register_forms')

    # Many-to-Many Relationship
    discounts = models.ManyToManyField(Discount, blank=True, related_name='register_forms')
    fileGroup = models.ForeignKey(RegistrationFileGroup,
                                 on_delete=models.SET_NULL,
                                 related_name='register_forms',
                                 null=True,
                                 blank=True)

    establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='register_forms')
    registration_payment = models.IntegerField(choices=PaymentModeType.choices, null=True, blank=True)
    tuition_payment = models.IntegerField(choices=PaymentModeType.choices, null=True, blank=True)
    registration_payment_plan = models.IntegerField(choices=PaymentPlanType.choices, null=True, blank=True)
    tuition_payment_plan = models.IntegerField(choices=PaymentPlanType.choices, null=True, blank=True)

    def __str__(self):
        return "RF_" + self.student.last_name + "_" + self.student.first_name

    def save(self, *args, **kwargs):
        # Vérifier si un fichier existant doit être remplacé
        if self.pk:  # Si l'objet existe déjà dans la base de données
            try:
                old_instance = RegistrationForm.objects.get(pk=self.pk)
                if old_instance.sepa_file and old_instance.sepa_file != self.sepa_file:
                    # Supprimer l'ancien fichier
                    old_instance.sepa_file.delete(save=False)
            except RegistrationForm.DoesNotExist:
                pass  # L'objet n'existe pas encore, rien à supprimer

        # Appeler la méthode save originale
        super().save(*args, **kwargs)

#############################################################
####################### MASTER FILES ########################
#############################################################

####### DocuSeal masters (documents école, à signer ou pas) #######
class RegistrationSchoolFileMaster(models.Model):
    groups = models.ManyToManyField(RegistrationFileGroup, related_name='school_file_masters', blank=True)
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255, default="")
    is_required = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.group.name} - {self.id}'

####### Parent files masters (documents à fournir par les parents) #######
class RegistrationParentFileMaster(models.Model):
    groups = models.ManyToManyField(RegistrationFileGroup, related_name='parent_file_masters', blank=True)
    name = models.CharField(max_length=255, default="")
    description = models.CharField(blank=True, null=True)

############################################################
####################### CLONE FILES ########################
############################################################

def registration_school_file_upload_to(instance, filename):
    return f"registration_files/dossier_rf_{instance.registration_form.pk}/school/{filename}"

def registration_parent_file_upload_to(instance, filename):
    return f"registration_files/dossier_rf_{instance.registration_form.pk}/parent/{filename}"

####### DocuSeal templates (par dossier d'inscription) #######
class RegistrationSchoolFileTemplate(models.Model):
    master = models.ForeignKey(RegistrationSchoolFileMaster, on_delete=models.CASCADE, related_name='school_file_templates', blank=True)
    id = models.IntegerField(primary_key=True)
    slug = models.CharField(max_length=255, default="")
    name = models.CharField(max_length=255, default="")
    registration_form = models.ForeignKey(RegistrationForm, on_delete=models.CASCADE, related_name='school_file_templates', blank=True)
    file = models.FileField(null=True,blank=True, upload_to=registration_school_file_upload_to)

    def __str__(self):
        return self.name

    @staticmethod
    def get_files_from_rf(register_form_id):
        """
        Récupère tous les fichiers liés à un dossier d’inscription donné.
        """
        registration_files = RegistrationSchoolFileTemplate.objects.filter(registration_form=register_form_id)
        filenames = []
        for reg_file in registration_files:
            filenames.append(reg_file.file.path)
        return filenames

####### Parent files templates (par dossier d'inscription) #######
class RegistrationParentFileTemplate(models.Model):
    master = models.ForeignKey(RegistrationParentFileMaster, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True)
    registration_form = models.ForeignKey(RegistrationForm, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True)
    file = models.FileField(null=True,blank=True, upload_to=registration_parent_file_upload_to)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if self.pk:  # Si l'objet existe déjà dans la base de données
            try:
                old_instance = RegistrationParentFileTemplate.objects.get(pk=self.pk)
                if old_instance.file and (not self.file or self.file.name == ''):
                    if os.path.exists(old_instance.file.path):
                        old_instance.file.delete(save=False)
                        self.file = None
                    else:
                        print(f"Le fichier {old_instance.file.path} n'existe pas.")
            except RegistrationParentFileTemplate.DoesNotExist:
                print("Ancienne instance introuvable.")
        super().save(*args, **kwargs)

    @staticmethod
    def get_files_from_rf(register_form_id):
        """
        Récupère tous les fichiers liés à un dossier d’inscription donné.
        """
        registration_files = RegistrationParentFileTemplate.objects.filter(registration_form=register_form_id)
        filenames = []
        for reg_file in registration_files:
            filenames.append(reg_file.file.path)
        return filenames
