package dev.lions.unionflow.client.dto;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * DTO côté client pour les données analytics
 * Enrichi avec des méthodes utilitaires pour l'affichage
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-17
 */
public class AnalyticsDataDTO implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
    
    private String id;
    private String typeMetrique;
    private String periodeAnalyse;
    private BigDecimal valeur;
    private BigDecimal valeurPrecedente;
    private BigDecimal pourcentageEvolution;
    private LocalDateTime dateDebut;
    private LocalDateTime dateFin;
    private LocalDateTime dateCalcul;
    private String organisationId;
    private String nomOrganisation;
    private String utilisateurId;
    private String nomUtilisateur;
    private String libellePersonnalise;
    private String description;
    private String donneesDetaillees;
    private String configurationGraphique;
    private Map<String, Object> metadonnees;
    private BigDecimal indicateurFiabilite;
    private Integer nombreElementsAnalyses;
    private Long tempsCalculMs;
    private Boolean tempsReel;
    private Boolean necessiteMiseAJour;
    private Integer niveauPriorite;
    private java.util.List<String> tags;
    
    // Getters et Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    
    public String getTypeMetrique() { return typeMetrique; }
    public void setTypeMetrique(String typeMetrique) { this.typeMetrique = typeMetrique; }
    
    public String getPeriodeAnalyse() { return periodeAnalyse; }
    public void setPeriodeAnalyse(String periodeAnalyse) { this.periodeAnalyse = periodeAnalyse; }
    
    public BigDecimal getValeur() { return valeur; }
    public void setValeur(BigDecimal valeur) { this.valeur = valeur; }
    
    public BigDecimal getValeurPrecedente() { return valeurPrecedente; }
    public void setValeurPrecedente(BigDecimal valeurPrecedente) { this.valeurPrecedente = valeurPrecedente; }
    
    public BigDecimal getPourcentageEvolution() { return pourcentageEvolution; }
    public void setPourcentageEvolution(BigDecimal pourcentageEvolution) { this.pourcentageEvolution = pourcentageEvolution; }
    
    public LocalDateTime getDateDebut() { return dateDebut; }
    public void setDateDebut(LocalDateTime dateDebut) { this.dateDebut = dateDebut; }
    
    public LocalDateTime getDateFin() { return dateFin; }
    public void setDateFin(LocalDateTime dateFin) { this.dateFin = dateFin; }
    
    public LocalDateTime getDateCalcul() { return dateCalcul; }
    public void setDateCalcul(LocalDateTime dateCalcul) { this.dateCalcul = dateCalcul; }
    
    public String getOrganisationId() { return organisationId; }
    public void setOrganisationId(String organisationId) { this.organisationId = organisationId; }
    
    public String getNomOrganisation() { return nomOrganisation; }
    public void setNomOrganisation(String nomOrganisation) { this.nomOrganisation = nomOrganisation; }
    
    public String getUtilisateurId() { return utilisateurId; }
    public void setUtilisateurId(String utilisateurId) { this.utilisateurId = utilisateurId; }
    
    public String getNomUtilisateur() { return nomUtilisateur; }
    public void setNomUtilisateur(String nomUtilisateur) { this.nomUtilisateur = nomUtilisateur; }
    
    public String getLibellePersonnalise() { return libellePersonnalise; }
    public void setLibellePersonnalise(String libellePersonnalise) { this.libellePersonnalise = libellePersonnalise; }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    
    public String getDonneesDetaillees() { return donneesDetaillees; }
    public void setDonneesDetaillees(String donneesDetaillees) { this.donneesDetaillees = donneesDetaillees; }
    
    public String getConfigurationGraphique() { return configurationGraphique; }
    public void setConfigurationGraphique(String configurationGraphique) { this.configurationGraphique = configurationGraphique; }
    
    public Map<String, Object> getMetadonnees() { return metadonnees; }
    public void setMetadonnees(Map<String, Object> metadonnees) { this.metadonnees = metadonnees; }
    
    public BigDecimal getIndicateurFiabilite() { return indicateurFiabilite; }
    public void setIndicateurFiabilite(BigDecimal indicateurFiabilite) { this.indicateurFiabilite = indicateurFiabilite; }
    
    public Integer getNombreElementsAnalyses() { return nombreElementsAnalyses; }
    public void setNombreElementsAnalyses(Integer nombreElementsAnalyses) { this.nombreElementsAnalyses = nombreElementsAnalyses; }
    
    public Long getTempsCalculMs() { return tempsCalculMs; }
    public void setTempsCalculMs(Long tempsCalculMs) { this.tempsCalculMs = tempsCalculMs; }
    
    public Boolean getTempsReel() { return tempsReel; }
    public void setTempsReel(Boolean tempsReel) { this.tempsReel = tempsReel; }
    
    public Boolean getNecessiteMiseAJour() { return necessiteMiseAJour; }
    public void setNecessiteMiseAJour(Boolean necessiteMiseAJour) { this.necessiteMiseAJour = necessiteMiseAJour; }
    
    public Integer getNiveauPriorite() { return niveauPriorite; }
    public void setNiveauPriorite(Integer niveauPriorite) { this.niveauPriorite = niveauPriorite; }
    
    public java.util.List<String> getTags() { return tags; }
    public void setTags(java.util.List<String> tags) { this.tags = tags; }
    
    // === MÉTHODES UTILITAIRES ===
    
    /**
     * Retourne le libellé à afficher
     */
    public String getLibelleAffichage() {
        if (libellePersonnalise != null && !libellePersonnalise.trim().isEmpty()) {
            return libellePersonnalise;
        }
        return typeMetrique != null ? typeMetrique : "Métrique";
    }
    
    /**
     * Retourne la valeur formatée
     */
    public String getValeurFormatee() {
        if (valeur == null) return "0";
        return valeur.toPlainString();
    }
    
    /**
     * Retourne le pourcentage d'évolution formaté
     */
    public String getEvolutionFormatee() {
        if (pourcentageEvolution == null) return "0%";
        String signe = pourcentageEvolution.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
        return signe + pourcentageEvolution.setScale(2, java.math.RoundingMode.HALF_UP) + "%";
    }
    
    /**
     * Retourne la couleur selon l'évolution
     */
    public String getCouleurEvolution() {
        if (pourcentageEvolution == null) return "text-600";
        if (pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0) return "text-green-500";
        if (pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0) return "text-red-500";
        return "text-600";
    }
    
    /**
     * Retourne l'icône selon l'évolution
     */
    public String getIconeEvolution() {
        if (pourcentageEvolution == null) return "pi pi-minus";
        if (pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0) return "pi pi-arrow-up";
        if (pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0) return "pi pi-arrow-down";
        return "pi pi-minus";
    }
    
    /**
     * Vérifie si l'évolution est positive
     */
    public boolean hasEvolutionPositive() {
        return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0;
    }
    
    /**
     * Vérifie si l'évolution est négative
     */
    public boolean hasEvolutionNegative() {
        return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0;
    }
    
    /**
     * Vérifie si les données sont fiables
     */
    public boolean isDonneesFiables() {
        return indicateurFiabilite != null && indicateurFiabilite.compareTo(new BigDecimal("80.0")) >= 0;
    }
    
    /**
     * Retourne la date de début formatée
     */
    public String getDateDebutFormatee() {
        if (dateDebut == null) return "";
        return dateDebut.format(DATE_FORMATTER);
    }
    
    /**
     * Retourne la date de fin formatée
     */
    public String getDateFinFormatee() {
        if (dateFin == null) return "";
        return dateFin.format(DATE_FORMATTER);
    }
    
    /**
     * Retourne la période formatée
     */
    public String getPeriodeFormatee() {
        return getDateDebutFormatee() + " - " + getDateFinFormatee();
    }
    
    /**
     * Convertit depuis une Map (réponse JSON du backend)
     */
    public static AnalyticsDataDTO fromMap(Map<String, Object> map) {
        AnalyticsDataDTO dto = new AnalyticsDataDTO();
        if (map == null) return dto;
        
        dto.setId((String) map.get("id"));
        dto.setTypeMetrique((String) map.get("typeMetrique"));
        dto.setPeriodeAnalyse((String) map.get("periodeAnalyse"));
        
        if (map.get("valeur") != null) {
            dto.setValeur(new BigDecimal(map.get("valeur").toString()));
        }
        if (map.get("valeurPrecedente") != null) {
            dto.setValeurPrecedente(new BigDecimal(map.get("valeurPrecedente").toString()));
        }
        if (map.get("pourcentageEvolution") != null) {
            dto.setPourcentageEvolution(new BigDecimal(map.get("pourcentageEvolution").toString()));
        }
        
        // Conversion des dates depuis des strings ISO
        if (map.get("dateDebut") != null) {
            dto.setDateDebut(parseDateTime(map.get("dateDebut").toString()));
        }
        if (map.get("dateFin") != null) {
            dto.setDateFin(parseDateTime(map.get("dateFin").toString()));
        }
        if (map.get("dateCalcul") != null) {
            dto.setDateCalcul(parseDateTime(map.get("dateCalcul").toString()));
        }
        
        dto.setOrganisationId((String) map.get("organisationId"));
        dto.setNomOrganisation((String) map.get("nomOrganisation"));
        dto.setUtilisateurId((String) map.get("utilisateurId"));
        dto.setNomUtilisateur((String) map.get("nomUtilisateur"));
        dto.setLibellePersonnalise((String) map.get("libellePersonnalise"));
        dto.setDescription((String) map.get("description"));
        dto.setDonneesDetaillees((String) map.get("donneesDetaillees"));
        dto.setConfigurationGraphique((String) map.get("configurationGraphique"));
        dto.setMetadonnees((Map<String, Object>) map.get("metadonnees"));
        
        if (map.get("indicateurFiabilite") != null) {
            dto.setIndicateurFiabilite(new BigDecimal(map.get("indicateurFiabilite").toString()));
        }
        if (map.get("nombreElementsAnalyses") != null) {
            dto.setNombreElementsAnalyses(Integer.valueOf(map.get("nombreElementsAnalyses").toString()));
        }
        if (map.get("tempsCalculMs") != null) {
            dto.setTempsCalculMs(Long.valueOf(map.get("tempsCalculMs").toString()));
        }
        
        dto.setTempsReel((Boolean) map.get("tempsReel"));
        dto.setNecessiteMiseAJour((Boolean) map.get("necessiteMiseAJour"));
        if (map.get("niveauPriorite") != null) {
            dto.setNiveauPriorite(Integer.valueOf(map.get("niveauPriorite").toString()));
        }
        
        @SuppressWarnings("unchecked")
        java.util.List<String> tagsList = (java.util.List<String>) map.get("tags");
        dto.setTags(tagsList);
        
        return dto;
    }
    
    /**
     * Parse une date depuis une string ISO
     */
    private static LocalDateTime parseDateTime(String dateStr) {
        if (dateStr == null || dateStr.isEmpty()) return null;
        try {
            // Format ISO: "2025-01-17T10:30:00" ou "2025-01-17 10:30:00"
            String normalized = dateStr.replace(" ", "T");
            if (normalized.length() == 10) {
                normalized += "T00:00:00";
            }
            return LocalDateTime.parse(normalized);
        } catch (Exception e) {
            return null;
        }
    }
}

