package dev.lions.unionflow.client.dto;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.UUID;

/**
 * DTO pour la gestion des cotisations côté client
 * Correspond au CotisationDTO du backend avec méthodes utilitaires pour l'affichage
 * 
 * @author UnionFlow Team
 * @version 1.0
 */
public class CotisationDTO implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    private UUID id;
    private String numeroReference;
    private UUID membreId;
    private String numeroMembre;
    private String nomMembre;
    private UUID associationId;
    private String nomAssociation;
    private String typeCotisation;
    private String libelle;
    private String description;
    private BigDecimal montantDu;
    private BigDecimal montantPaye;
    private String codeDevise;
    private String statut;
    private LocalDate dateEcheance;
    private LocalDateTime datePaiement;
    private String methodePaiement;
    private String referencePaiement;
    private String observations;
    private LocalDateTime dateCreation;
    private String waveSessionId;
    
    // Getters et Setters
    public UUID getId() { return id; }
    public void setId(UUID id) { this.id = id; }
    
    public String getNumeroReference() { return numeroReference; }
    public void setNumeroReference(String numeroReference) { this.numeroReference = numeroReference; }
    
    public UUID getMembreId() { return membreId; }
    public void setMembreId(UUID membreId) { this.membreId = membreId; }
    
    public String getNumeroMembre() { return numeroMembre; }
    public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
    
    public String getNomMembre() { return nomMembre; }
    public void setNomMembre(String nomMembre) { this.nomMembre = nomMembre; }
    
    public UUID getAssociationId() { return associationId; }
    public void setAssociationId(UUID associationId) { this.associationId = associationId; }
    
    public String getNomAssociation() { return nomAssociation; }
    public void setNomAssociation(String nomAssociation) { this.nomAssociation = nomAssociation; }
    
    public String getTypeCotisation() { return typeCotisation; }
    public void setTypeCotisation(String typeCotisation) { this.typeCotisation = typeCotisation; }
    
    public String getLibelle() { return libelle; }
    public void setLibelle(String libelle) { this.libelle = libelle; }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    
    public BigDecimal getMontantDu() { return montantDu; }
    public void setMontantDu(BigDecimal montantDu) { this.montantDu = montantDu; }
    
    public BigDecimal getMontantPaye() { return montantPaye != null ? montantPaye : BigDecimal.ZERO; }
    public void setMontantPaye(BigDecimal montantPaye) { this.montantPaye = montantPaye; }
    
    public String getCodeDevise() { return codeDevise; }
    public void setCodeDevise(String codeDevise) { this.codeDevise = codeDevise; }
    
    public String getStatut() { return statut; }
    public void setStatut(String statut) { this.statut = statut; }
    
    public LocalDate getDateEcheance() { return dateEcheance; }
    public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
    
    public LocalDateTime getDatePaiement() { return datePaiement; }
    public void setDatePaiement(LocalDateTime datePaiement) { this.datePaiement = datePaiement; }
    
    public String getMethodePaiement() { return methodePaiement; }
    public void setMethodePaiement(String methodePaiement) { this.methodePaiement = methodePaiement; }
    
    public String getReferencePaiement() { return referencePaiement; }
    public void setReferencePaiement(String referencePaiement) { this.referencePaiement = referencePaiement; }
    
    public String getObservations() { return observations; }
    public void setObservations(String observations) { this.observations = observations; }
    
    public LocalDateTime getDateCreation() { return dateCreation; }
    public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
    
    public String getWaveSessionId() { return waveSessionId; }
    public void setWaveSessionId(String waveSessionId) { this.waveSessionId = waveSessionId; }
    
    // Méthodes utilitaires pour l'affichage (alignées avec le backend)
    
    /**
     * Vérifie si la cotisation est payée intégralement
     */
    public boolean isPayeeIntegralement() {
        return montantPaye != null && montantDu != null && montantPaye.compareTo(montantDu) >= 0;
    }
    
    /**
     * Vérifie si la cotisation est en retard
     */
    public boolean isEnRetard() {
        return dateEcheance != null && LocalDate.now().isAfter(dateEcheance) && !isPayeeIntegralement();
    }
    
    /**
     * Calcule le montant restant à payer
     */
    public BigDecimal getMontantRestant() {
        if (montantDu == null) return BigDecimal.ZERO;
        if (montantPaye == null) return montantDu;
        BigDecimal restant = montantDu.subtract(montantPaye);
        return restant.compareTo(BigDecimal.ZERO) > 0 ? restant : BigDecimal.ZERO;
    }
    
    /**
     * Calcule le pourcentage de paiement
     */
    public int getPourcentagePaiement() {
        if (montantDu == null || montantDu.compareTo(BigDecimal.ZERO) == 0) return 0;
        if (montantPaye == null) return 0;
        return montantPaye.multiply(BigDecimal.valueOf(100))
                .divide(montantDu, 0, java.math.RoundingMode.HALF_UP)
                .intValue();
    }
    
    /**
     * Calcule le nombre de jours de retard
     */
    public long getJoursRetard() {
        if (dateEcheance == null || !isEnRetard()) return 0;
        return ChronoUnit.DAYS.between(dateEcheance, LocalDate.now());
    }
    
    /**
     * Retourne le libellé du type de cotisation
     */
    public String getTypeCotisationLibelle() {
        if (typeCotisation == null) return "Non défini";
        return switch (typeCotisation) {
            case "MENSUELLE" -> "Mensuelle";
            case "TRIMESTRIELLE" -> "Trimestrielle";
            case "SEMESTRIELLE" -> "Semestrielle";
            case "ANNUELLE" -> "Annuelle";
            case "EXCEPTIONNELLE" -> "Exceptionnelle";
            case "ADHESION" -> "Adhésion";
            default -> typeCotisation;
        };
    }
    
    /**
     * Retourne le libellé du statut
     */
    public String getStatutLibelle() {
        if (statut == null) return "Non défini";
        return switch (statut) {
            case "EN_ATTENTE" -> "En attente";
            case "PAYEE" -> "Payée";
            case "PARTIELLEMENT_PAYEE" -> "Partiellement payée";
            case "EN_RETARD" -> "En retard";
            case "ANNULEE" -> "Annulée";
            case "REMBOURSEE" -> "Remboursée";
            default -> statut;
        };
    }
    
    /**
     * Retourne le libellé de la méthode de paiement
     */
    public String getMethodePaiementLibelle() {
        if (methodePaiement == null) return "Non défini";
        return switch (methodePaiement) {
            case "ESPECES" -> "Espèces";
            case "VIREMENT" -> "Virement bancaire";
            case "CHEQUE" -> "Chèque";
            case "WAVE_MONEY" -> "Wave Money";
            case "ORANGE_MONEY" -> "Orange Money";
            case "FREE_MONEY" -> "Free Money";
            case "CARTE_BANCAIRE" -> "Carte bancaire";
            default -> methodePaiement;
        };
    }
    
    /**
     * Retourne la sévérité du statut pour PrimeFaces
     */
    public String getStatutSeverity() {
        if (statut == null) return "secondary";
        return switch (statut) {
            case "PAYEE" -> "success";
            case "EN_ATTENTE" -> "warning";
            case "EN_RETARD" -> "danger";
            case "PARTIELLEMENT_PAYEE" -> "info";
            case "ANNULEE", "REMBOURSEE" -> "secondary";
            default -> "secondary";
        };
    }
    
    /**
     * Retourne l'icône du statut pour PrimeFaces
     */
    public String getStatutIcon() {
        if (statut == null) return "pi-circle";
        return switch (statut) {
            case "PAYEE" -> "pi-check";
            case "EN_ATTENTE" -> "pi-clock";
            case "EN_RETARD" -> "pi-exclamation-triangle";
            case "PARTIELLEMENT_PAYEE" -> "pi-minus";
            default -> "pi-circle";
        };
    }
    
    /**
     * Formate la date d'échéance
     */
    public String getDateEcheanceFormatee() {
        if (dateEcheance == null) return "";
        return dateEcheance.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
    }
    
    /**
     * Formate la date de paiement
     */
    public String getDatePaiementFormatee() {
        if (datePaiement == null) return "";
        return datePaiement.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
    }
    
    /**
     * Formate le montant dû
     */
    public String getMontantDuFormatte() {
        if (montantDu == null) return "0 FCFA";
        return String.format("%,.0f FCFA", montantDu.doubleValue());
    }
    
    /**
     * Formate le montant payé
     */
    public String getMontantPayeFormatte() {
        if (montantPaye == null) return "0 FCFA";
        return String.format("%,.0f FCFA", montantPaye.doubleValue());
    }
    
    /**
     * Formate le montant restant
     */
    public String getMontantRestantFormatte() {
        return String.format("%,.0f FCFA", getMontantRestant().doubleValue());
    }
}

