package dev.lions.unionflow.client.dto;

import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

public class SouscriptionDTO implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    public enum StatutSouscription {
        ACTIVE("Actif", "text-green-600", "bg-green-100"),
        SUSPENDUE("Suspendue", "text-orange-600", "bg-orange-100"),
        EXPIREE("Expirée", "text-red-600", "bg-red-100"),
        EN_ATTENTE_PAIEMENT("En attente de paiement", "text-blue-600", "bg-blue-100"),
        ANNULEE("Annulée", "text-gray-600", "bg-gray-100");
        
        private final String libelle;
        private final String couleurTexte;
        private final String couleurFond;
        
        StatutSouscription(String libelle, String couleurTexte, String couleurFond) {
            this.libelle = libelle;
            this.couleurTexte = couleurTexte;
            this.couleurFond = couleurFond;
        }
        
        public String getLibelle() { return libelle; }
        public String getCouleurTexte() { return couleurTexte; }
        public String getCouleurFond() { return couleurFond; }
    }
    
    public enum TypeFacturation {
        MENSUEL("Mensuel"),
        ANNUEL("Annuel");
        
        private final String libelle;
        
        TypeFacturation(String libelle) {
            this.libelle = libelle;
        }
        
        public String getLibelle() { return libelle; }
    }
    
    private Long id;
    
    @NotNull
    private Long organisationId;
    private String organisationNom;
    
    @NotNull
    private Long formulaireId;
    private String formulaireNom;
    
    @NotNull
    private StatutSouscription statut;
    
    @NotNull
    private TypeFacturation typeFacturation;
    
    @NotNull
    private LocalDate dateDebut;
    
    @NotNull
    private LocalDate dateFin;
    
    private LocalDate dateDernierPaiement;
    private LocalDate dateProchainPaiement;
    
    @NotNull
    private Integer quotaMaxMembres;
    
    private Integer membresActuels = 0;
    
    @NotNull
    private BigDecimal montantSouscription;
    
    private String deviseCode = "XOF";
    
    private String numeroFacture;
    private String referencePaiement;
    
    // Informations de renouvellement automatique
    private boolean renouvellementAutomatique = false;
    private String methodePaiementDefaut;
    
    // Notifications
    private boolean notificationExpiration = true;
    private boolean notificationQuotaAtteint = true;
    private int joursAvantNotificationExpiration = 30;
    
    // Audit
    private LocalDateTime dateCreation;
    private LocalDateTime dateMiseAJour;
    private String creePar;
    private String modifiePar;
    
    public SouscriptionDTO() {}
    
    // Getters et Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public Long getOrganisationId() { return organisationId; }
    public void setOrganisationId(Long organisationId) { this.organisationId = organisationId; }
    
    public String getOrganisationNom() { return organisationNom; }
    public void setOrganisationNom(String organisationNom) { this.organisationNom = organisationNom; }
    
    public Long getFormulaireId() { return formulaireId; }
    public void setFormulaireId(Long formulaireId) { this.formulaireId = formulaireId; }
    
    public String getFormulaireNom() { return formulaireNom; }
    public void setFormulaireNom(String formulaireNom) { this.formulaireNom = formulaireNom; }
    
    public StatutSouscription getStatut() { return statut; }
    public void setStatut(StatutSouscription statut) { this.statut = statut; }
    
    public TypeFacturation getTypeFacturation() { return typeFacturation; }
    public void setTypeFacturation(TypeFacturation typeFacturation) { this.typeFacturation = typeFacturation; }
    
    public LocalDate getDateDebut() { return dateDebut; }
    public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
    
    public LocalDate getDateFin() { return dateFin; }
    public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
    
    public LocalDate getDateDernierPaiement() { return dateDernierPaiement; }
    public void setDateDernierPaiement(LocalDate dateDernierPaiement) { this.dateDernierPaiement = dateDernierPaiement; }
    
    public LocalDate getDateProchainPaiement() { return dateProchainPaiement; }
    public void setDateProchainPaiement(LocalDate dateProchainPaiement) { this.dateProchainPaiement = dateProchainPaiement; }
    
    public Integer getQuotaMaxMembres() { return quotaMaxMembres; }
    public void setQuotaMaxMembres(Integer quotaMaxMembres) { this.quotaMaxMembres = quotaMaxMembres; }
    
    public Integer getMembresActuels() { return membresActuels; }
    public void setMembresActuels(Integer membresActuels) { this.membresActuels = membresActuels; }
    
    public BigDecimal getMontantSouscription() { return montantSouscription; }
    public void setMontantSouscription(BigDecimal montantSouscription) { this.montantSouscription = montantSouscription; }
    
    public String getDeviseCode() { return deviseCode; }
    public void setDeviseCode(String deviseCode) { this.deviseCode = deviseCode; }
    
    public String getNumeroFacture() { return numeroFacture; }
    public void setNumeroFacture(String numeroFacture) { this.numeroFacture = numeroFacture; }
    
    public String getReferencePaiement() { return referencePaiement; }
    public void setReferencePaiement(String referencePaiement) { this.referencePaiement = referencePaiement; }
    
    public boolean isRenouvellementAutomatique() { return renouvellementAutomatique; }
    public void setRenouvellementAutomatique(boolean renouvellementAutomatique) { this.renouvellementAutomatique = renouvellementAutomatique; }
    
    public String getMethodePaiementDefaut() { return methodePaiementDefaut; }
    public void setMethodePaiementDefaut(String methodePaiementDefaut) { this.methodePaiementDefaut = methodePaiementDefaut; }
    
    public boolean isNotificationExpiration() { return notificationExpiration; }
    public void setNotificationExpiration(boolean notificationExpiration) { this.notificationExpiration = notificationExpiration; }
    
    public boolean isNotificationQuotaAtteint() { return notificationQuotaAtteint; }
    public void setNotificationQuotaAtteint(boolean notificationQuotaAtteint) { this.notificationQuotaAtteint = notificationQuotaAtteint; }
    
    public int getJoursAvantNotificationExpiration() { return joursAvantNotificationExpiration; }
    public void setJoursAvantNotificationExpiration(int joursAvantNotificationExpiration) { this.joursAvantNotificationExpiration = joursAvantNotificationExpiration; }
    
    public LocalDateTime getDateCreation() { return dateCreation; }
    public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
    
    public LocalDateTime getDateMiseAJour() { return dateMiseAJour; }
    public void setDateMiseAJour(LocalDateTime dateMiseAJour) { this.dateMiseAJour = dateMiseAJour; }
    
    public String getCreePar() { return creePar; }
    public void setCreePar(String creePar) { this.creePar = creePar; }
    
    public String getModifiePar() { return modifiePar; }
    public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
    
    // Méthodes utilitaires
    public boolean isActive() {
        return statut == StatutSouscription.ACTIVE && !isExpiree();
    }
    
    public boolean isExpiree() {
        return LocalDate.now().isAfter(dateFin);
    }
    
    public boolean isQuotaAtteint() {
        return membresActuels != null && quotaMaxMembres != null && 
               membresActuels >= quotaMaxMembres;
    }
    
    public int getMembresRestants() {
        if (membresActuels != null && quotaMaxMembres != null) {
            return Math.max(0, quotaMaxMembres - membresActuels);
        }
        return 0;
    }
    
    public int getPourcentageUtilisation() {
        if (membresActuels != null && quotaMaxMembres != null && quotaMaxMembres > 0) {
            return (membresActuels * 100) / quotaMaxMembres;
        }
        return 0;
    }
    
    public String getMontantFormat() {
        if (montantSouscription != null) {
            return String.format("%,.0f %s", montantSouscription, deviseCode);
        }
        return "0 " + deviseCode;
    }
    
    public String getStatutCouleurClass() {
        return statut != null ? statut.getCouleurTexte() : "text-gray-600";
    }
    
    public String getStatutFondClass() {
        return statut != null ? statut.getCouleurFond() : "bg-gray-100";
    }
    
    public String getStatutLibelle() {
        return statut != null ? statut.getLibelle() : "Inconnu";
    }
    
    public long getJoursRestants() {
        if (dateFin != null) {
            return LocalDate.now().until(dateFin).getDays();
        }
        return 0;
    }
    
    public boolean isExpirationProche() {
        long joursRestants = getJoursRestants();
        return joursRestants <= joursAvantNotificationExpiration && joursRestants > 0;
    }
}