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.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.UUID;

/**
 * DTO pour la gestion des événements côté client
 * Correspond au EvenementDTO du backend avec méthodes utilitaires pour l'affichage
 * 
 * @author UnionFlow Team
 * @version 2.0
 */
public class EvenementDTO implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // Propriétés de base
    private UUID id;
    private String titre;
    private String description;
    private String typeEvenement; // ASSEMBLEE_GENERALE, FORMATION, etc.
    private String statut; // PLANIFIE, CONFIRME, EN_COURS, TERMINE, ANNULE, REPORTE
    private String priorite; // CRITIQUE, HAUTE, NORMALE, BASSE
    
    // Dates et heures
    private LocalDate dateDebut;
    private LocalDate dateFin;
    private LocalTime heureDebut;
    private LocalTime heureFin;
    private LocalDate dateLimiteInscription;
    
    // Localisation
    private String lieu;
    private String adresse;
    private String ville;
    private String region;
    private BigDecimal latitude;
    private BigDecimal longitude;
    
    // Organisation
    private UUID associationId;
    private String nomAssociation;
    private String organisateur;
    private String emailOrganisateur;
    private String telephoneOrganisateur;
    
    // Participants
    private Integer capaciteMax;
    private Integer participantsInscrits;
    private Integer participantsPresents;
    
    // Budget
    private BigDecimal budget;
    private BigDecimal coutReel;
    private String codeDevise;
    
    // Options
    private Boolean inscriptionObligatoire;
    private Boolean evenementPublic;
    private Boolean recurrent;
    private String frequenceRecurrence;
    
    // Informations complémentaires
    private String instructions;
    private String materielNecessaire;
    private String conditionsMeteo;
    private String imageUrl;
    private String couleurTheme;
    
    // Annulation
    private LocalDateTime dateAnnulation;
    private String raisonAnnulation;
    private String nomAnnulateur;
    
    // Métadonnées
    private LocalDateTime dateCreation;
    private LocalDateTime dateModification;
    
    // Getters et Setters
    public UUID getId() { return id; }
    public void setId(UUID id) { this.id = id; }
    
    public String getTitre() { return titre; }
    public void setTitre(String titre) { this.titre = titre; }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    
    public String getTypeEvenement() { return typeEvenement; }
    public void setTypeEvenement(String typeEvenement) { this.typeEvenement = typeEvenement; }
    
    public String getStatut() { return statut; }
    public void setStatut(String statut) { this.statut = statut; }
    
    public String getPriorite() { return priorite; }
    public void setPriorite(String priorite) { this.priorite = priorite; }
    
    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 LocalTime getHeureDebut() { return heureDebut; }
    public void setHeureDebut(LocalTime heureDebut) { this.heureDebut = heureDebut; }
    
    public LocalTime getHeureFin() { return heureFin; }
    public void setHeureFin(LocalTime heureFin) { this.heureFin = heureFin; }
    
    public LocalDate getDateLimiteInscription() { return dateLimiteInscription; }
    public void setDateLimiteInscription(LocalDate dateLimiteInscription) { this.dateLimiteInscription = dateLimiteInscription; }
    
    public String getLieu() { return lieu; }
    public void setLieu(String lieu) { this.lieu = lieu; }
    
    public String getAdresse() { return adresse; }
    public void setAdresse(String adresse) { this.adresse = adresse; }
    
    public String getVille() { return ville; }
    public void setVille(String ville) { this.ville = ville; }
    
    public String getRegion() { return region; }
    public void setRegion(String region) { this.region = region; }
    
    public BigDecimal getLatitude() { return latitude; }
    public void setLatitude(BigDecimal latitude) { this.latitude = latitude; }
    
    public BigDecimal getLongitude() { return longitude; }
    public void setLongitude(BigDecimal longitude) { this.longitude = longitude; }
    
    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 getOrganisateur() { return organisateur; }
    public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
    
    public String getEmailOrganisateur() { return emailOrganisateur; }
    public void setEmailOrganisateur(String emailOrganisateur) { this.emailOrganisateur = emailOrganisateur; }
    
    public String getTelephoneOrganisateur() { return telephoneOrganisateur; }
    public void setTelephoneOrganisateur(String telephoneOrganisateur) { this.telephoneOrganisateur = telephoneOrganisateur; }
    
    public Integer getCapaciteMax() { return capaciteMax; }
    public void setCapaciteMax(Integer capaciteMax) { this.capaciteMax = capaciteMax; }
    
    public Integer getParticipantsInscrits() { return participantsInscrits != null ? participantsInscrits : 0; }
    public void setParticipantsInscrits(Integer participantsInscrits) { this.participantsInscrits = participantsInscrits; }
    
    public Integer getParticipantsPresents() { return participantsPresents != null ? participantsPresents : 0; }
    public void setParticipantsPresents(Integer participantsPresents) { this.participantsPresents = participantsPresents; }
    
    public BigDecimal getBudget() { return budget; }
    public void setBudget(BigDecimal budget) { this.budget = budget; }
    
    public BigDecimal getCoutReel() { return coutReel; }
    public void setCoutReel(BigDecimal coutReel) { this.coutReel = coutReel; }
    
    public String getCodeDevise() { return codeDevise != null ? codeDevise : "XOF"; }
    public void setCodeDevise(String codeDevise) { this.codeDevise = codeDevise; }
    
    public Boolean getInscriptionObligatoire() { return inscriptionObligatoire != null ? inscriptionObligatoire : false; }
    public void setInscriptionObligatoire(Boolean inscriptionObligatoire) { this.inscriptionObligatoire = inscriptionObligatoire; }
    
    public Boolean getEvenementPublic() { return evenementPublic != null ? evenementPublic : true; }
    public void setEvenementPublic(Boolean evenementPublic) { this.evenementPublic = evenementPublic; }
    
    public Boolean getRecurrent() { return recurrent != null ? recurrent : false; }
    public void setRecurrent(Boolean recurrent) { this.recurrent = recurrent; }
    
    public String getFrequenceRecurrence() { return frequenceRecurrence; }
    public void setFrequenceRecurrence(String frequenceRecurrence) { this.frequenceRecurrence = frequenceRecurrence; }
    
    public String getInstructions() { return instructions; }
    public void setInstructions(String instructions) { this.instructions = instructions; }
    
    public String getMaterielNecessaire() { return materielNecessaire; }
    public void setMaterielNecessaire(String materielNecessaire) { this.materielNecessaire = materielNecessaire; }
    
    public String getConditionsMeteo() { return conditionsMeteo; }
    public void setConditionsMeteo(String conditionsMeteo) { this.conditionsMeteo = conditionsMeteo; }
    
    public String getImageUrl() { return imageUrl; }
    public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
    
    public String getCouleurTheme() { return couleurTheme; }
    public void setCouleurTheme(String couleurTheme) { this.couleurTheme = couleurTheme; }
    
    public LocalDateTime getDateAnnulation() { return dateAnnulation; }
    public void setDateAnnulation(LocalDateTime dateAnnulation) { this.dateAnnulation = dateAnnulation; }
    
    public String getRaisonAnnulation() { return raisonAnnulation; }
    public void setRaisonAnnulation(String raisonAnnulation) { this.raisonAnnulation = raisonAnnulation; }
    
    public String getNomAnnulateur() { return nomAnnulateur; }
    public void setNomAnnulateur(String nomAnnulateur) { this.nomAnnulateur = nomAnnulateur; }
    
    public LocalDateTime getDateCreation() { return dateCreation; }
    public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
    
    public LocalDateTime getDateModification() { return dateModification; }
    public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
    
    // Méthodes utilitaires pour l'affichage
    
    /**
     * Retourne le libellé du type d'événement
     */
    public String getTypeEvenementLibelle() {
        if (typeEvenement == null) return "Non défini";
        return switch (typeEvenement) {
            case "ASSEMBLEE_GENERALE" -> "Assemblée Générale";
            case "FORMATION" -> "Formation";
            case "ACTIVITE_SOCIALE" -> "Activité Sociale";
            case "ACTION_CARITATIVE" -> "Action Caritative";
            case "REUNION_BUREAU" -> "Réunion de Bureau";
            case "CONFERENCE" -> "Conférence";
            case "ATELIER" -> "Atelier";
            case "CEREMONIE" -> "Cérémonie";
            case "AUTRE" -> "Autre";
            default -> typeEvenement;
        };
    }
    
    /**
     * Retourne la sévérité PrimeFaces pour le type
     */
    public String getTypeEvenementSeverity() {
        if (typeEvenement == null) return "info";
        return switch (typeEvenement) {
            case "ASSEMBLEE_GENERALE" -> "danger";
            case "REUNION_BUREAU" -> "warning";
            case "FORMATION" -> "success";
            case "ACTION_CARITATIVE" -> "info";
            case "ACTIVITE_SOCIALE" -> "secondary";
            default -> "primary";
        };
    }
    
    /**
     * Retourne l'icône PrimeFaces pour le type
     */
    public String getTypeEvenementIcon() {
        if (typeEvenement == null) return "pi-calendar";
        return switch (typeEvenement) {
            case "ASSEMBLEE_GENERALE" -> "pi-sitemap";
            case "REUNION_BUREAU" -> "pi-users";
            case "FORMATION" -> "pi-book";
            case "ACTION_CARITATIVE", "ACTIVITE_SOCIALE" -> "pi-heart";
            case "CONFERENCE" -> "pi-microphone";
            case "ATELIER" -> "pi-wrench";
            case "CEREMONIE" -> "pi-star";
            default -> "pi-calendar";
        };
    }
    
    /**
     * Retourne le libellé du statut
     */
    public String getStatutLibelle() {
        if (statut == null) return "Non défini";
        return switch (statut) {
            case "PLANIFIE" -> "Planifié";
            case "CONFIRME" -> "Confirmé";
            case "EN_COURS" -> "En cours";
            case "TERMINE" -> "Terminé";
            case "ANNULE" -> "Annulé";
            case "REPORTE" -> "Reporté";
            default -> statut;
        };
    }
    
    /**
     * Retourne la sévérité PrimeFaces pour le statut
     */
    public String getStatutSeverity() {
        if (statut == null) return "info";
        return switch (statut) {
            case "PLANIFIE" -> "info";
            case "CONFIRME" -> "success";
            case "EN_COURS" -> "warning";
            case "TERMINE" -> "success";
            case "ANNULE" -> "error";
            case "REPORTE" -> "warn";
            default -> "info";
        };
    }
    
    /**
     * Retourne l'icône PrimeFaces pour le statut
     */
    public String getStatutIcon() {
        if (statut == null) return "pi-circle";
        return switch (statut) {
            case "PLANIFIE" -> "pi-clock";
            case "CONFIRME" -> "pi-check-circle";
            case "EN_COURS" -> "pi-play";
            case "TERMINE" -> "pi-check";
            case "ANNULE" -> "pi-ban";
            case "REPORTE" -> "pi-calendar-times";
            default -> "pi-circle";
        };
    }
    
    /**
     * Retourne le libellé de la priorité
     */
    public String getPrioriteLibelle() {
        if (priorite == null) return "Normale";
        return switch (priorite) {
            case "CRITIQUE" -> "Critique";
            case "HAUTE" -> "Haute";
            case "NORMALE" -> "Normale";
            case "BASSE" -> "Basse";
            default -> priorite;
        };
    }
    
    /**
     * Retourne la sévérité PrimeFaces pour la priorité
     */
    public String getPrioriteSeverity() {
        if (priorite == null) return "info";
        return switch (priorite) {
            case "CRITIQUE" -> "error";
            case "HAUTE" -> "warning";
            case "NORMALE" -> "info";
            case "BASSE" -> "secondary";
            default -> "info";
        };
    }
    
    /**
     * Formate la date de début
     */
    public String getDateDebutFormatee() {
        if (dateDebut == null) return "";
        return dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
    }
    
    /**
     * Formate la date de fin
     */
    public String getDateFinFormatee() {
        if (dateFin == null) return "";
        return dateFin.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
    }
    
    /**
     * Formate l'heure de début
     */
    public String getHeureDebutFormatee() {
        if (heureDebut == null) return "";
        return heureDebut.format(DateTimeFormatter.ofPattern("HH:mm"));
    }
    
    /**
     * Formate l'heure de fin
     */
    public String getHeureFinFormatee() {
        if (heureFin == null) return "";
        return heureFin.format(DateTimeFormatter.ofPattern("HH:mm"));
    }
    
    /**
     * Formate le budget
     */
    public String getBudgetFormate() {
        if (budget == null) return "0 FCFA";
        return String.format("%,.0f %s", budget.doubleValue(), getCodeDevise());
    }
    
    /**
     * Calcule le nombre de places disponibles
     */
    public int getPlacesDisponibles() {
        if (capaciteMax == null || capaciteMax == 0) return 0;
        int inscrits = getParticipantsInscrits();
        return Math.max(0, capaciteMax - inscrits);
    }
    
    /**
     * Calcule le taux de remplissage en pourcentage
     */
    public int getTauxRemplissage() {
        if (capaciteMax == null || capaciteMax == 0) return 0;
        int inscrits = getParticipantsInscrits();
        return (inscrits * 100) / capaciteMax;
    }
    
    /**
     * Calcule le taux de présence en pourcentage
     */
    public int getTauxPresence() {
        int inscrits = getParticipantsInscrits();
        if (inscrits == 0) return 0;
        int presents = getParticipantsPresents();
        return (presents * 100) / inscrits;
    }
    
    /**
     * Calcule le nombre de jours restants avant l'événement
     */
    public long getJoursRestants() {
        if (dateDebut == null) return 0;
        return ChronoUnit.DAYS.between(LocalDate.now(), dateDebut);
    }
    
    /**
     * Vérifie si l'événement est complet
     */
    public boolean isComplet() {
        if (capaciteMax == null || capaciteMax == 0) return false;
        return getParticipantsInscrits() >= capaciteMax;
    }
    
    /**
     * Vérifie si l'événement est en cours
     */
    public boolean isEnCours() {
        return "EN_COURS".equals(statut);
    }
    
    /**
     * Vérifie si l'événement est terminé
     */
    public boolean isTermine() {
        return "TERMINE".equals(statut);
    }
    
    /**
     * Vérifie si l'événement est annulé
     */
    public boolean isAnnule() {
        return "ANNULE".equals(statut);
    }
    
    /**
     * Vérifie si les inscriptions sont ouvertes
     */
    public boolean sontInscriptionsOuvertes() {
        if (isAnnule() || isTermine()) return false;
        if (dateLimiteInscription != null && LocalDate.now().isAfter(dateLimiteInscription)) return false;
        return !isComplet();
    }
    
    /**
     * Retourne l'adresse complète formatée
     */
    public String getAdresseComplete() {
        StringBuilder sb = new StringBuilder();
        if (lieu != null && !lieu.trim().isEmpty()) {
            sb.append(lieu);
        }
        if (adresse != null && !adresse.trim().isEmpty()) {
            if (sb.length() > 0) sb.append(", ");
            sb.append(adresse);
        }
        if (ville != null && !ville.trim().isEmpty()) {
            if (sb.length() > 0) sb.append(", ");
            sb.append(ville);
        }
        if (region != null && !region.trim().isEmpty()) {
            if (sb.length() > 0) sb.append(", ");
            sb.append(region);
        }
        return sb.toString();
    }
    
    /**
     * Calcule la durée en heures
     */
    public long getDureeEnHeures() {
        if (heureDebut == null || heureFin == null) return 0;
        return ChronoUnit.HOURS.between(heureDebut, heureFin);
    }
    
    /**
     * Vérifie si l'événement dure plusieurs jours
     */
    public boolean isEvenementMultiJours() {
        return dateFin != null && dateDebut != null && !dateDebut.equals(dateFin);
    }
}
