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

import dev.lions.unionflow.server.api.dto.base.BaseResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;

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 événement.
 */
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EvenementResponse extends BaseResponse {

    private String titre;
    private String description;
    private TypeEvenementMetier typeEvenement;
    private StatutEvenement statut;
    private PrioriteEvenement priorite;

    // Décommenter si l'on a besoin du @JsonFormat, sinon on garde le standard
    // @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate dateDebut;

    // @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate dateFin;

    // @JsonFormat(pattern = "HH:mm")
    private LocalTime heureDebut;

    // @JsonFormat(pattern = "HH:mm")
    private LocalTime heureFin;
    private String lieu;
    private String adresse;
    private String ville;
    private String region;
    private BigDecimal latitude;
    private BigDecimal longitude;
    private UUID associationId;
    private String nomAssociation;
    private String organisateur;
    private String emailOrganisateur;
    private String telephoneOrganisateur;
    private Integer capaciteMax;
    private Integer participantsInscrits;
    private Integer participantsPresents;
    private BigDecimal budget;
    private BigDecimal coutReel;
    private String codeDevise;
    private Boolean inscriptionObligatoire;

    // @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate dateLimiteInscription;

    private Boolean evenementPublic;
    private Boolean recurrent;
    private String frequenceRecurrence;
    private String instructions;
    private String materielNecessaire;
    private String conditionsMeteo;
    private String imageUrl;
    private String couleurTheme;

    // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime dateAnnulation;
    private String raisonAnnulation;
    private String nomAnnulateur;
    private Long annulePar;

    // === METHODES UTILITAIRES ===

    public boolean estEnCours() {
        return StatutEvenement.EN_COURS.equals(statut);
    }

    public boolean estTermine() {
        return StatutEvenement.TERMINE.equals(statut);
    }

    public boolean estAnnule() {
        return StatutEvenement.ANNULE.equals(statut);
    }

    public boolean estComplet() {
        return capaciteMax != null
                && participantsInscrits != null
                && participantsInscrits >= capaciteMax;
    }

    public int getPlacesDisponibles() {
        if (capaciteMax == null || participantsInscrits == null) {
            return 0;
        }
        return Math.max(0, capaciteMax - participantsInscrits);
    }

    public int getTauxRemplissage() {
        if (capaciteMax == null || capaciteMax == 0 || participantsInscrits == null) {
            return 0;
        }
        return (participantsInscrits * 100) / capaciteMax;
    }

    public int getTauxPresence() {
        if (participantsInscrits == null || participantsInscrits == 0 || participantsPresents == null) {
            return 0;
        }
        return (participantsPresents * 100) / participantsInscrits;
    }

    public boolean sontInscriptionsOuvertes() {
        if (estAnnule() || estTermine()) {
            return false;
        }

        if (dateLimiteInscription != null && LocalDate.now().isAfter(dateLimiteInscription)) {
            return false;
        }

        return !estComplet();
    }

    public long getDureeEnHeures() {
        if (heureDebut == null || heureFin == null) {
            return 0;
        }

        return heureDebut.until(heureFin, java.time.temporal.ChronoUnit.HOURS);
    }

    public boolean estEvenementMultiJours() {
        return dateFin != null && !dateDebut.equals(dateFin);
    }

    public String getTypeEvenementLibelle() {
        return typeEvenement != null ? typeEvenement.getLibelle() : "Non défini";
    }

    public String getStatutLibelle() {
        return statut != null ? statut.getLibelle() : "Non défini";
    }

    public String getPrioriteLibelle() {
        return priorite != null ? priorite.getLibelle() : "Normale";
    }

    public String getAdresseComplete() {
        StringBuilder adresseComplete = new StringBuilder();

        if (lieu != null && !lieu.trim().isEmpty()) {
            adresseComplete.append(lieu);
        }

        if (adresse != null && !adresse.trim().isEmpty()) {
            if (adresseComplete.length() > 0)
                adresseComplete.append(", ");
            adresseComplete.append(adresse);
        }

        if (ville != null && !ville.trim().isEmpty()) {
            if (adresseComplete.length() > 0)
                adresseComplete.append(", ");
            adresseComplete.append(ville);
        }

        if (region != null && !region.trim().isEmpty()) {
            if (adresseComplete.length() > 0)
                adresseComplete.append(", ");
            adresseComplete.append(region);
        }

        return adresseComplete.toString();
    }

    public boolean hasCoordonnees() {
        return latitude != null && longitude != null;
    }

    public BigDecimal getEcartBudgetaire() {
        if (budget == null || coutReel == null) {
            return BigDecimal.ZERO;
        }
        return budget.subtract(coutReel);
    }

    public boolean estBudgetDepasse() {
        return getEcartBudgetaire().compareTo(BigDecimal.ZERO) < 0;
    }
}
