from django.conf import settings
from django.db import models
from django.utils import timezone
from decimal import Decimal
from dgi.models import *
import dgi.models as dgi_models # Pour accès explicite aux modèles DGI (pour héritage)

class Timespanmodel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Client(dgi_models.Client):
    # Les champs suivants font doublon avec ceux de dgi.models.Client mais portent des noms différents,
    # on les garde pour la compatibilité existante, mais idéalement il faudrait migrer vers les champs DGI (name, address, contact).
    nom = models.CharField(max_length=200)
    adresse = models.TextField(blank=True)
    
    # email existe déjà dans dgi.models.Client, on doit le désactiver ici pour éviter le conflit MTI
    # email = models.EmailField(blank=True) 
    
    telephone = models.CharField(max_length=50, blank=True)
    solde_compte = models.DecimalField(max_digits=14, decimal_places=2, default=0.00)
    
    # created_at est hérité de Timespanmodel via dgi.models.Client
    # created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.nom

class TypeDossier(models.Model):
    designation = models.CharField(max_length=100, unique=True, verbose_name="Désignation")
    description = models.TextField(blank=True, verbose_name="Description")
    
    def __str__(self):
        return self.designation

class TypeService(models.Model):
    code = models.CharField(max_length=50, unique=True)
    designation = models.CharField(max_length=255)
    actif = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.code} - {self.designation}"

class Service(Article_Dgi):
    type_service = models.ForeignKey(TypeService, on_delete=models.CASCADE, related_name='services')
    code = models.CharField(max_length=50, unique=True)
    designation = models.CharField(max_length=255)
    actif = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.code} - {self.designation}"

class FraisStandard(models.Model):
    """Catalogue des frais standards"""
    DEVISE_CHOICES = [
        ('FC', 'Franc Congolais'),
        ('USD', 'Dollar Américain'),
    ]
    nom = models.CharField(max_length=200)
    montant_defaut = models.DecimalField(max_digits=12, decimal_places=2, default=0.00)
    devise_defaut = models.CharField(max_length=3, choices=DEVISE_CHOICES, default='USD')
    est_soumis_tva = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.nom} ({self.montant_defaut} {self.devise_defaut})"

class Dossier(models.Model):
    STATUT_CHOICES = [
        ('BROUILLON', 'Brouillon'),
        ('EN_COURS', 'En cours'),
        ('FACTURE', 'Facturé'),
        ('CLOTURE', 'Clôturé'),
    ]

    # --- Informations Générales ---
    numero = models.CharField(max_length=50, unique=True, verbose_name="Numéro Dossier")
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='dossiers')
    ref_client = models.CharField(max_length=100, blank=True, verbose_name="Réf. Client")
    type_dossier = models.ForeignKey(TypeDossier, on_delete=models.SET_NULL, null=True, blank=True, related_name='dossiers', verbose_name="Type de Dossier")
    description = models.CharField(max_length=255, verbose_name="Marchandise / Description")
    date_ouverture = models.DateTimeField(default=timezone.now)
    statut = models.CharField(max_length=20, choices=STATUT_CHOICES, default='BROUILLON')

    # --- Transport & Marchandise ---
    vol = models.CharField(max_length=50, blank=True, verbose_name="Vol")
    date_arrivee = models.DateField(null=True, blank=True, verbose_name="Date d'arrivée")
    mawb = models.CharField(max_length=50, blank=True, verbose_name="MAWB")
    hawb = models.CharField(max_length=50, blank=True, verbose_name="HAWB")
    manifeste = models.CharField(max_length=50, blank=True, verbose_name="Manifeste")
    date_manifeste = models.DateField(null=True, blank=True, verbose_name="Date Manifeste")
    
    nombre_colis = models.IntegerField(default=0, verbose_name="Nombre de colis")
    poids = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name="Poids (Kg)")
    
    # --- Valeurs & Tarifaire ---
    achat_laisser_suivre = models.CharField(max_length=100, blank=True, verbose_name="Achat Laisser-suivre")
    mt_laisser_suivre_cdf = models.DecimalField(max_digits=14, decimal_places=2, default=0.00, verbose_name="Mt L/S CDF")
    mt_laisser_suivre_usd = models.DecimalField(max_digits=14, decimal_places=2, default=0.00, verbose_name="Mt L/S USD")
    taux_laisser_suivre = models.DecimalField(max_digits=10, decimal_places=4, default=0.00, verbose_name="Tx L/S")
    date_laisser_suivre = models.DateField(null=True, blank=True, verbose_name="Date L/S")

    facture_fournisseur = models.CharField(max_length=100, blank=True, verbose_name="Facture Fournisseur")
    valeur_cif_fc = models.DecimalField(max_digits=16, decimal_places=2, default=0.00, verbose_name="Valeur CIF FC")
    taux_change = models.DecimalField(max_digits=10, decimal_places=4, default=0.00, verbose_name="Taux (Tx)")
    valeur_cif_usd = models.DecimalField(max_digits=16, decimal_places=2, default=0.00, verbose_name="Valeur CIF USD")
    
    positions_tarifaires = models.CharField(max_length=100, blank=True, verbose_name="Positions tarifaires")
    taux_douane = models.CharField(max_length=50, blank=True, verbose_name="Taux Douane (%)")
    
    # --- Documents & Certificats ---
    attest_verification = models.CharField(max_length=100, blank=True, verbose_name="Attest. de vérific.")
    licence = models.CharField(max_length=100, blank=True, verbose_name="Licence")
    fxi = models.CharField(max_length=100, blank=True, verbose_name="FXI")
    
    avis_arrivee = models.CharField(max_length=100, blank=True, verbose_name="Avis d'arrivée")
    reserves = models.CharField(max_length=200, blank=True, verbose_name="Réserves")
    date_reserves = models.DateField(null=True, blank=True, verbose_name="Date Réserves")
    
    attestation_fiscale = models.CharField(max_length=100, blank=True, verbose_name="Attestation fiscale")
    validite_fiscale_du = models.DateField(null=True, blank=True, verbose_name="Validité Fiscale Du")
    validite_fiscale_au = models.DateField(null=True, blank=True, verbose_name="Validité Fiscale Au")

    # --- Déclarations & Procédures (Colonne Gauche) ---
    declaration_dgda = models.CharField(max_length=50, blank=True, verbose_name="Déclaration DGDA n°")
    date_declaration_dgda = models.DateField(null=True, blank=True, verbose_name="Date Déclaration DGDA")
    
    bordereau_versement = models.CharField(max_length=50, blank=True, verbose_name="Bordereau de versement n°")
    date_bordereau_versement = models.DateField(null=True, blank=True, verbose_name="Date Bordereau")
    
    bordereau_versement_fb = models.CharField(max_length=50, blank=True, verbose_name="Bordereau de versement Fb n°")
    date_bordereau_versement_fb = models.DateField(null=True, blank=True, verbose_name="Date Bordereau Fb")
    
    bulletin_liquidation = models.CharField(max_length=50, blank=True, verbose_name="Bulletin de Liquidation")
    date_bulletin_liquidation = models.DateField(null=True, blank=True, verbose_name="Date Bulletin")
    
    bon_a_enlever = models.CharField(max_length=50, blank=True, verbose_name="Bon à enlever N°")
    date_bon_a_enlever = models.DateField(null=True, blank=True, verbose_name="Date Bon à enlever")
    
    bon_de_sortie = models.CharField(max_length=50, blank=True, verbose_name="Bon de sortie N°")
    date_bon_de_sortie = models.DateField(null=True, blank=True, verbose_name="Date Bon de sortie")
    
    num_enlevement_autorise = models.CharField(max_length=50, blank=True, verbose_name="N° Enlevement Autorisé")
    date_enlevement_autorise = models.DateField(null=True, blank=True, verbose_name="Date Enlevement")
    
    declaration_exoneration = models.CharField(max_length=50, blank=True, verbose_name="Déclaration en Exonération")
    date_declaration_exoneration = models.DateField(null=True, blank=True, verbose_name="Date Exonération")
    
    transit_magasinage = models.CharField(max_length=50, blank=True, verbose_name="Transit & Magasinage")
    date_transit_magasinage = models.DateField(null=True, blank=True, verbose_name="Date Transit")
    
    recu_occ = models.CharField(max_length=50, blank=True, verbose_name="Reçu OCC N°")
    date_recu_occ = models.DateField(null=True, blank=True, verbose_name="Date Reçu OCC")
    
    note_debit_occ = models.CharField(max_length=50, blank=True, verbose_name="Note de débit OCC")
    date_note_debit_occ = models.DateField(null=True, blank=True, verbose_name="Date ND OCC")
    
    rapport_controle_occ = models.CharField(max_length=50, blank=True, verbose_name="Rapport de contrôle OCC")
    date_rapport_controle_occ = models.DateField(null=True, blank=True, verbose_name="Date Rapport OCC")

    # --- Suivi des Dates ---
    date_introduction_douane = models.DateField(null=True, blank=True, verbose_name="Date Introduction douane")
    date_verification = models.DateField(null=True, blank=True, verbose_name="Date Vérification")
    date_paiement_douane = models.DateField(null=True, blank=True, verbose_name="Date Payement Douane")
    date_sortie_douane = models.DateField(null=True, blank=True, verbose_name="Sortie Douane le")

    bon_livraison = models.CharField(max_length=50, blank=True, verbose_name="Bon de livraison n°")
    date_bon_livraison = models.DateField(null=True, blank=True, verbose_name="Date Bon de livraison")
    
    transm_documents_n = models.CharField(max_length=50, blank=True, verbose_name="Transm documents n°")
    date_transm_documents = models.DateField(null=True, blank=True, verbose_name="Transm de documents le")

    # --- Intervenants ---
    calcule_par = models.CharField(max_length=100, blank=True, verbose_name="Calculé par")
    dactylo_par = models.CharField(max_length=100, blank=True, verbose_name="Dactylo par")
    declarant = models.CharField(max_length=100, blank=True, verbose_name="Déclarant")

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        if not self.numero:
            # Sauvegarder d'abord pour obtenir un ID
            super().save(*args, **kwargs)
            # Générer le numéro basé sur l'année et l'ID
            self.numero = f"DOS-{timezone.now().year}-{self.id:04d}"
            # Mettre à jour seulement le champ numero pour éviter une boucle ou des appels inutiles
            kwargs.pop('force_insert', None)  # Enlever force_insert s'il existe
            super(Dossier, self).save(update_fields=['numero'])
        else:
            super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.numero} - {self.client.nom}"

    @property
    def total_frais_usd(self):
        # Utilise le code 'FRAIS' dans TypeService
        return sum(l.montant for l in self.lignes.filter(service__type_service__code='FRAIS', devise='USD'))
    
    @property
    def total_debours_usd(self):
        # Utilise le code 'DEBOURS' dans TypeService
        return sum(l.montant for l in self.lignes.filter(service__type_service__code='DEBOURS', devise='USD'))

class LigneDossier(models.Model):
    DEVISE_CHOICES = [
        ('FC', 'Franc Congolais'),
        ('USD', 'Dollar Américain'),
    ]

    dossier = models.ForeignKey(Dossier, on_delete=models.CASCADE, related_name='lignes')
    service = models.ForeignKey(Service, on_delete=models.PROTECT, related_name='lignes', null=True)
    montant = models.DecimalField(max_digits=12, decimal_places=2, default=0.00)
    devise = models.CharField(max_length=3, choices=DEVISE_CHOICES, default='USD')
    
    # Nouveaux champs pour conversion
    taux = models.DecimalField(max_digits=10, decimal_places=4, default=0.00, verbose_name="Taux Echange")
    montant_conversion = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name="Montant Converti")
    
    class Meta:
        unique_together = ['dossier', 'service']

    def __str__(self):
        # Handle case where service might be null temporarily (though theoretically shouldn't happen after valid save)
        service_name = self.service.designation if self.service else "Service Inconnu"
        return f"{service_name} ({self.montant} {self.devise})"

class Proforma(models.Model):
    STATUT_CHOICES = [
        ('BROUILLON', 'Brouillon'),
        ('VALIDEE', 'Validée'),
        ('REJETEE', 'Rejetée'),
    ]
    TYPE_PROFORMA_CHOICES = [
        ('FV', 'Facture de Vente'),
        ('FS', 'Facture de Situation'),
        ('FA', "Facture d'Avoir"),
    ]

    type_proforma = models.CharField(max_length=2, choices=TYPE_PROFORMA_CHOICES, default='FV', verbose_name="Type de Proforma")

    # Client direct (nouveau flux sans dossier)
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='proformas', null=True, blank=True)
    objet = models.CharField(max_length=255, verbose_name="Objet / Titre de la mission", blank=True)

    # Commentaire / bloc destinataire (affiché sur PDF en lieu des montants contractuels)
    commentaire = models.TextField(blank=True, verbose_name="Commentaire / Bloc Destinataire")

    # Lien dossier conservé pour compatibilité avec l'ancien flux
    dossier = models.ForeignKey(Dossier, on_delete=models.SET_NULL, related_name='proformas', null=True, blank=True)

    numero = models.CharField(max_length=50, unique=True, editable=False)
    date_emission = models.DateTimeField(default=timezone.now)
    statut = models.CharField(max_length=20, choices=STATUT_CHOICES, default='BROUILLON')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='proformas_crees')

    def get_client(self):
        """Retourne le client depuis proforma.client ou via dossier (compat)."""
        return self.client or (self.dossier.client if self.dossier else None)

    def save(self, *args, **kwargs):
        if not self.numero:
            year = timezone.now().year
            count =Proforma.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/FAC/ {count:03d}/{year}"
        super().save(*args, **kwargs)

    def __str__(self):
        client = self.get_client()
        return f"{self.numero} – {client.nom if client else 'Sans client'}"


class LigneProforma(models.Model):
    DEVISE_CHOICES = [
        ('FC', 'Franc Congolais'),
        ('USD', 'Dollar Américain'),
    ]

    proforma = models.ForeignKey(Proforma, on_delete=models.CASCADE, related_name='lignes')
    designation = models.CharField(max_length=255, verbose_name="Désignation")
    description = models.TextField(blank=True, verbose_name="Description détaillée")
    quantite = models.DecimalField(max_digits=10, decimal_places=2, default=1, verbose_name="Quantité")
    prix_unitaire = models.DecimalField(max_digits=12, decimal_places=2, default=0, verbose_name="Prix Unitaire (USD)")
    montant = models.DecimalField(max_digits=12, decimal_places=2, default=0, verbose_name="Montant (USD)")
    devise = models.CharField(max_length=3, choices=DEVISE_CHOICES, default='USD')

    # Champs en Francs Congolais pour la normalisation DGI
    prix_unitaire_fc = models.DecimalField(max_digits=16, decimal_places=2, default=0, verbose_name="Prix Unitaire (FC)")
    montant_fc = models.DecimalField(max_digits=16, decimal_places=2, default=0, verbose_name="Montant (FC)")

    def save(self, *args, **kwargs):
        from decimal import Decimal
        self.montant = self.quantite * self.prix_unitaire
        # Récupérer le taux depuis les infos société (table Societe)
        try:
            societe = Societe.objects.filter(est_actif=True).first()
            taux_fc = Decimal(str(societe.taux)) if societe and societe.taux else Decimal('2800')
        except Exception:
            taux_fc = Decimal('2800')
        self.prix_unitaire_fc = self.prix_unitaire * taux_fc
        self.montant_fc = self.montant * taux_fc
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.designation} – {self.montant} {self.devise}"


class Proforma_model2(Timespanmodel):
    STATUT_CHOICES = [
        ('BROUILLON', 'Brouillon'),
        ('VALIDEE', 'Validée'),
        ('REJETEE', 'Rejetée'),
    ]
    TYPE_PROFORMA_CHOICES = [
        ('FV', 'Facture de Vente'),
        ('FS', 'Facture de Situation'),
        ('FA', "Facture d'Avoir"),
    ]

    type_proforma = models.CharField(max_length=2, choices=TYPE_PROFORMA_CHOICES, default='FV', verbose_name="Type de Proforma")

    # Client direct (nouveau flux sans dossier)
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='proformas_m2', null=True, blank=True)
    objet = models.CharField(max_length=255, verbose_name="Objet / Titre de la mission", blank=True)

    # Montants contractuels
    montant_marche = models.DecimalField(max_digits=14, decimal_places=2, default=0, verbose_name="Montant du Marché (USD)")
    montant_demande = models.DecimalField(max_digits=14, decimal_places=2, default=0, verbose_name="Montant Demandé (USD)")
    montant_sollicite = models.DecimalField(max_digits=14, decimal_places=2, default=0, verbose_name="Montant Sollicité (USD)")

    # Commentaire / bloc destinataire
    commentaire = models.TextField(blank=True, verbose_name="Commentaire / Bloc Destinataire")

    numero = models.CharField(max_length=50, unique=True, editable=False)
    date_emission = models.DateTimeField(default=timezone.now)
    statut = models.CharField(max_length=20, choices=STATUT_CHOICES, default='BROUILLON')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='proformas_m2_crees')

    def get_client(self):
        return self.client

    @property
    def total_lignes_marche(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_marche'))['total'] or 0

    @property
    def total_lignes_demande(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_demande'))['total'] or 0

    def save(self, *args, **kwargs):
        if not self.numero:
            import datetime
            year = timezone.now().year
            count =Proforma_model2.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/FACM2/ {count:03d}/{year}"
        super().save(*args, **kwargs)

    def __str__(self):
        client = self.get_client()
        return f"{self.numero} – {client.nom if client else 'Sans client'}"


class LigneProforma_model2(Timespanmodel):
    proforma = models.ForeignKey(Proforma_model2, on_delete=models.CASCADE, related_name='lignes')
    ordre = models.PositiveSmallIntegerField(default=1, verbose_name="N")
    designation = models.CharField(max_length=255, verbose_name="Étape / Désignation")
    montant_marche = models.DecimalField(max_digits=14, decimal_places=2, default=0, null=True, blank=True, verbose_name="Montant du Marché (USD)")
    montant_demande = models.DecimalField(max_digits=14, decimal_places=2, default=0, null=True, blank=True, verbose_name="Montant Demandé (USD)")

    class Meta:
        ordering = ['ordre']

    def __str__(self):
        return f"{self.ordre}. {self.designation}"


class Proforma_model3(Timespanmodel):
    STATUT_CHOICES = [
        ('BROUILLON', 'Brouillon'),
        ('VALIDEE', 'Validée'),
        ('REJETEE', 'Rejetée'),
    ]
    TYPE_PROFORMA_CHOICES = [
        ('FV', 'Facture de Vente'),
        ('FS', 'Facture de Situation'),
        ('FA', "Facture d'Avoir"),
    ]

    type_proforma = models.CharField(max_length=2, choices=TYPE_PROFORMA_CHOICES, default='FV', verbose_name="Type de Proforma")

    # Client direct (nouveau flux sans dossier)
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='proformas_m3', null=True, blank=True)
    objet = models.CharField(max_length=255, verbose_name="Objet / Titre de la mission", blank=True)

    # Commentaire / bloc destinataire
    commentaire = models.TextField(blank=True, verbose_name="Commentaire / Bloc Destinataire")

    numero = models.CharField(max_length=50, unique=True, editable=False)
    date_emission = models.DateTimeField(default=timezone.now)
    statut = models.CharField(max_length=20, choices=STATUT_CHOICES, default='BROUILLON')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='proformas_m3_crees')

    def get_client(self):
        return self.client

    @property
    def total_lignes_marche(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_marche'))['total'] or 0

    @property
    def total_lignes_percu(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_percu'))['total'] or 0

    @property
    def total_lignes_restant(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_restant'))['total'] or 0

    @property
    def total_lignes_sollicite(self):
        from django.db.models import Sum
        return self.lignes.aggregate(total=Sum('montant_sollicite'))['total'] or 0

    def save(self, *args, **kwargs):
        if not self.numero:
            import datetime
            year = timezone.now().year
            count =Proforma_model3.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/FACM3/ {count:03d}/{year}"
        super().save(*args, **kwargs)

    def __str__(self):
        client = self.get_client()
        return f"{self.numero} – {client.nom if client else 'Sans client'}"


class LigneProforma_model3(Timespanmodel):
    proforma = models.ForeignKey(Proforma_model3, on_delete=models.CASCADE, related_name='lignes')
    ordre = models.PositiveSmallIntegerField(default=1, verbose_name="N")
    designation = models.CharField(max_length=255, verbose_name="Étape / Désignation")
    montant_marche = models.DecimalField(max_digits=14, decimal_places=2, default=0, null=True, blank=True, verbose_name="Montant du Marché (USD)")
    montant_percu = models.DecimalField(max_digits=14, decimal_places=2, default=0, null=True, blank=True, verbose_name="Montant Perçu (USD)")
    montant_restant = models.DecimalField(max_digits=14, decimal_places=2, default=0, verbose_name="Montant Restant (USD)")
    montant_sollicite = models.DecimalField(max_digits=14, decimal_places=2, default=0, verbose_name="Montant Sollicité (USD)")

    class Meta:
        ordering = ['ordre']

    def __str__(self):
        return f"{self.ordre}. {self.designation}"

class Facture(Commande_Dgi):
    proforma = models.OneToOneField(Proforma, on_delete=models.PROTECT, related_name='facture')
    dossier = models.ForeignKey(Dossier, on_delete=models.SET_NULL, null=True, blank=True, related_name='factures')
    numero = models.CharField(max_length=50, unique=True)
    date_emission = models.DateTimeField(default=timezone.now)
    fichier_pdf = models.FileField(upload_to='factures/', null=True, blank=True)
    
    facture_originale = models.ForeignKey("self", on_delete=models.SET_NULL, null=True, blank=True, related_name="factures_avoir")
    est_annulee = models.BooleanField(default=False)
    motif_annulation = models.CharField(max_length=255, blank=True)
    is_deleted = models.BooleanField(default=False, verbose_name="Supprimé logiquement")
    TYPE_FACTURE_CHOICES = [
        ('FV', 'Facture de Vente'),        ('FS', 'Facture de Situation'),        ('FA', 'Facture d\'Avoir'),
    ]
    #taux_conversion_fc = models.DecimalField(max_digits=15, decimal_places=4, default=2800.00, verbose_name="Taux de conversion FC")

    type_facture = models.CharField(max_length=2, choices=TYPE_FACTURE_CHOICES, default='FV')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='factures_crees')
    
    class Meta:
        ordering = ['-date_emission']

    def save(self, *args, **kwargs):
        if not self.numero:
            year = timezone.now().year
            count = Facture.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/ {count:03d}/{year}"
            
        super().save(*args, **kwargs)


class FactureM2(Commande_Dgi):
    """Facture liée à une Proforma Étapes (model 2)."""
    proforma = models.OneToOneField(Proforma_model2, on_delete=models.PROTECT, related_name='facture')
    numero = models.CharField(max_length=50, unique=True)
    date_emission = models.DateTimeField(default=timezone.now)
    fichier_pdf = models.FileField(upload_to='factures_m2/', null=True, blank=True)
    est_annulee = models.BooleanField(default=False)
    motif_annulation = models.CharField(max_length=255, blank=True)
    is_deleted = models.BooleanField(default=False, verbose_name="Supprimé logiquement")
    TYPE_FACTURE_CHOICES = [
        ('FV', 'Facture de Vente'),
        ('FS', 'Facture de Situation'),
        ('FA', "Facture d'Avoir"),
    ]
    type_facture = models.CharField(max_length=2, choices=TYPE_FACTURE_CHOICES, default='FS')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='factures_m2_crees')

    class Meta:
        ordering = ['-date_emission']

    def save(self, *args, **kwargs):
        if not self.numero:
            year = timezone.now().year
            count = FactureM2.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/M2/{count:03d}/{year}"
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.numero} – {self.proforma.numero}"


class FactureM3(Commande_Dgi):
    """Facture liée à une Proforma Situation (model 3)."""
    proforma = models.OneToOneField(Proforma_model3, on_delete=models.PROTECT, related_name='facture')
    numero = models.CharField(max_length=50, unique=True)
    date_emission = models.DateTimeField(default=timezone.now)
    fichier_pdf = models.FileField(upload_to='factures_m3/', null=True, blank=True)
    est_annulee = models.BooleanField(default=False)
    motif_annulation = models.CharField(max_length=255, blank=True)
    is_deleted = models.BooleanField(default=False, verbose_name="Supprimé logiquement")
    TYPE_FACTURE_CHOICES = [
        ('FV', 'Facture de Vente'),
        ('FS', 'Facture de Situation'),
        ('FA', "Facture d'Avoir"),
    ]
    type_facture = models.CharField(max_length=2, choices=TYPE_FACTURE_CHOICES, default='FS')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='factures_m3_crees')

    class Meta:
        ordering = ['-date_emission']

    def save(self, *args, **kwargs):
        if not self.numero:
            year = timezone.now().year
            count = FactureM3.objects.filter(date_emission__year=year).count() + 1
            self.numero = f"CET/M3/{count:03d}/{year}"
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.numero} – {self.proforma.numero}"

class Paiement(models.Model):
    DEVISE_CHOICES = [
        ('FC', 'Franc Congolais'),
        ('USD', 'Dollar Américain'),
    ]
    
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='paiements')
    facture = models.ForeignKey(Facture, on_delete=models.SET_NULL, null=True, blank=True, related_name='paiements')
    montant = models.DecimalField(max_digits=12, decimal_places=2)
    devise = models.CharField(max_length=3, choices=DEVISE_CHOICES)
    date_paiement = models.DateField(default=timezone.now)
    reference = models.CharField(max_length=100, help_text="Numéro de chèque, virement, etc.")
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True, related_name='paiements_crees')
    
    created_at = models.DateTimeField(auto_now_add=True)

class EcritureComptable(models.Model):
    SENS_CHOICES = [
        ('DEBIT', 'Débit'),
        ('CREDIT', 'Crédit'),
    ]
    
    client = models.ForeignKey(Client, on_delete=models.PROTECT, related_name='ecritures')
    date_ecriture = models.DateTimeField(auto_now_add=True)
    libelle = models.CharField(max_length=255)
    montant = models.DecimalField(max_digits=14, decimal_places=2)
    sens = models.CharField(max_length=10, choices=SENS_CHOICES)
    
    # Audit links
    facture_liee = models.ForeignKey(Facture, on_delete=models.SET_NULL, null=True, blank=True)
    paiement_lie = models.ForeignKey(Paiement, on_delete=models.SET_NULL, null=True, blank=True)
    
    def __str__(self):
        return f"{self.date_ecriture} - {self.client} - {self.sens} {self.montant}"

class Societe(Pointvente_Dgi):
    nom = models.CharField(max_length=255, default="AGIL s.a.r.l.")
    sous_titre = models.CharField(max_length=255, default="Agence Internationale de Logistique, Transit et Services")
    
    # Adresses
    adresse_physique = models.TextField(default="Avenue ex Poids Lourds n° 1963 (Concession Sucrière)\nKinshasa : Gombe - République Démocratique du Congo")
    
    # Admin / Fiscal
    rccm = models.CharField(max_length=100, default="CD/KIN/RCCM/14-B-01536")
    id_nat = models.CharField(max_length=100, default="01-718-N63783F")
    n_impot = models.CharField(max_length=100, default="A1116228C")
    
    # Contacts
    site_web = models.CharField(max_length=255, default="www.agil.cd")
    telephone_1 = models.CharField(max_length=50, default="00 243 89 700 16 73")
    telephone_2 = models.CharField(max_length=50, default="00 243 89 700 16 71")
    email_general = models.EmailField(default="secretariat@agil.cd")
    email_secondaire = models.EmailField(blank=True, null=True, default="m-laschet@agil.cd")
    email_tertiaire = models.EmailField(blank=True, null=True, default="c-kutu@agil.cd")
    
    # Banque
    compte_bancaire_usd = models.CharField(max_length=100, blank=True, null=True, verbose_name="Compte Bancaire USD")
    compte_bancaire_cdf = models.CharField(max_length=100, default="BCDC : 00011-00101-00001122 363-40/CDF", verbose_name="Compte Bancaire CDF")
    taux = models.CharField(max_length=255, default="2250")

    est_actif = models.BooleanField(default=True, help_text="Si coché, ces infos seront utilisées par défaut.")

    class Meta:
        verbose_name = "Info Société"
        verbose_name_plural = "Infos Société"

    def __str__(self):
        return self.nom


class Droit(models.Model):
    class Meta:
        permissions = (
            ('administrateur', 'Onglet Administrateur'),
            ('dossier', 'Onglet Dossier'),
        )