package dev.lions.unionflow.server.api.dto.abonnement.response;

import dev.lions.unionflow.server.api.dto.base.BaseResponse;
import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * Réponse détaillée pour un abonnement.
 */
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AbonnementResponse extends BaseResponse {

    private String numeroReference;
    private UUID organisationId;
    private String nomOrganisation;
    private UUID formulaireId;
    private String codeFormule;
    private String nomFormule;
    private TypeFormule typeFormule;
    private StatutAbonnement statut;
    private TypePeriodeAbonnement typeAbonnement;
    private LocalDate dateDebut;
    private LocalDate dateFin;
    private LocalDate dateProchainePeriode;
    private BigDecimal montant;
    private String devise;
    private BigDecimal remise;
    private BigDecimal montantFinal;
    private Boolean renouvellementAutomatique;
    private Boolean periodeEssaiUtilisee;
    private LocalDate dateFinEssai;
    private Integer maxMembres;
    private Integer nombreMembresActuels;
    private BigDecimal espaceStockageGB;
    private BigDecimal espaceStockageUtilise;
    private Boolean supportTechnique;
    private String niveauSupport;
    private Boolean fonctionnalitesAvancees;
    private Boolean apiAccess;
    private Boolean rapportsPersonnalises;
    private Boolean integrationsTierces;
    private LocalDateTime dateDerniereUtilisation;
    private Integer connexionsCeMois;
    private UUID responsableId;
    private String nomResponsable;
    private String emailResponsable;
    private String telephoneResponsable;

    private String modePaiementPrefere;
    private String numeroPaiementMobile;
    private String historiquePaiements;
    private String notes;

    private Boolean alertesActivees;
    private Boolean notificationsEmail;
    private Boolean notificationsSMS;

    private LocalDateTime dateSuspension;

    private String raisonSuspension;

    private LocalDateTime dateAnnulation;

    private String raisonAnnulation;

    // === MÉTHODES UTILITAIRES ===

    public boolean isActive() {
        return StatutAbonnement.ACTIF.equals(statut);
    }

    public boolean isExpire() {
        return StatutAbonnement.EXPIRE.equals(statut) ||
                (dateFin != null && dateFin.isBefore(LocalDate.now()));
    }

    public boolean isSuspendu() {
        return StatutAbonnement.SUSPENDU.equals(statut);
    }

    public int getMembresRestants() {
        if (maxMembres == null) return 0;
        int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
        return Math.max(0, maxMembres - actuels);
    }

    public boolean isQuotaAtteint() {
        if (maxMembres == null) return false;
        int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
        return actuels >= maxMembres;
    }

    public int getPourcentageUtilisation() {
        if (maxMembres == null || maxMembres == 0) return 0;
        int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
        return (actuels * 100) / maxMembres;
    }

    public long getJoursRestants() {
        if (dateFin == null) return -1;
        LocalDate maintenant = LocalDate.now();
        if (maintenant.isAfter(dateFin)) return 0;
        return java.time.temporal.ChronoUnit.DAYS.between(maintenant, dateFin);
    }

    public boolean isExpirationProche() {
        long joursRestants = getJoursRestants();
        return joursRestants >= 0 && joursRestants <= 30;
    }

    public boolean peutEtreRenouvele() {
        return Boolean.TRUE.equals(renouvellementAutomatique) && !isExpire();
    }

    public String getStatutLibelle() {
        return statut != null ? statut.name() : "INCONNU";
    }
}
