package dev.lions.btpxpress.view;

import com.fasterxml.jackson.databind.JsonNode;
import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import dev.lions.btpxpress.service.DashboardService;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Bean de vue pour le tableau de bord principal.
 * 
 * <p>Ce bean charge et affiche les métriques réelles provenant de l'API backend.
 * Toutes les données sont récupérées depuis l'API, aucune donnée fictive n'est utilisée.</p>
 * 
 * @author BTP Xpress Team
 * @version 1.0
 */
@Named("dashboardView")
@ViewScoped
@Getter
@Setter
public class DashboardView implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(DashboardView.class);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    @Inject
    private DashboardService dashboardService;

    // Métriques principales
    private long nombreChantiers = 0;
    private long chantiersActifs = 0;
    private long nombreClients = 0;
    private long nombreDevis = 0;
    private long facturesImpayees = 0;
    private double chiffreAffairesMois = 0.0;
    private double budgetTotal = 0.0;
    private double budgetConsomme = 0.0;

    // Métriques ressources
    private long nombreEquipes = 0;
    private long equipesDisponibles = 0;
    private long nombreEmployes = 0;
    private long nombreMateriel = 0;
    private long materielDisponible = 0;

    // Métriques maintenance
    private long maintenancesEnRetard = 0;
    private long maintenancesPlanifiees = 0;

    // Alertes
    private long totalAlertes = 0;
    private boolean alerteCritique = false;

    // Chantiers récents
    private List<ChantierResume> chantiersRecents = new ArrayList<>();
    private List<ChantierResume> chantiersEnRetard = new ArrayList<>();

    /**
     * Initialise le dashboard en chargeant toutes les données depuis l'API.
     */
    @PostConstruct
    public void init() {
        logger.info("Initialisation du dashboard avec données réelles de l'API");
        loadDashboardPrincipal();
        loadDashboardChantiers();
        loadDashboardFinances();
        loadDashboardRessources();
        loadDashboardMaintenance();
        loadAlertes();
        loadNombreClients();
        loadNombreDevis();
        loadNombreFacturesImpayees();
    }

    /**
     * Charge les métriques du dashboard principal.
     */
    private void loadDashboardPrincipal() {
        try {
            JsonNode dashboard = dashboardService.getDashboardPrincipal();
            if (dashboard != null) {
                JsonNode chantiers = dashboard.get("chantiers");
                if (chantiers != null) {
                    nombreChantiers = chantiers.get("total").asLong(0);
                    chantiersActifs = chantiers.get("actifs").asLong(0);
                }
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement du dashboard principal", e);
        }
    }

    /**
     * Charge les métriques des chantiers.
     */
    private void loadDashboardChantiers() {
        try {
            JsonNode dashboard = dashboardService.getDashboardChantiers();
            if (dashboard != null) {
                JsonNode chantiersActifsNode = dashboard.get("chantiersActifs");
                if (chantiersActifsNode != null && chantiersActifsNode.isArray()) {
                    chantiersRecents.clear();
                    Iterator<JsonNode> iterator = chantiersActifsNode.elements();
                    int count = 0;
                    while (iterator.hasNext() && count < 5) {
                        JsonNode chantier = iterator.next();
                        ChantierResume c = new ChantierResume();
                        c.setId(chantier.get("id").asText());
                        c.setNom(chantier.get("nom").asText(""));
                        c.setClient(chantier.get("client").asText("Non assigné"));
                        if (chantier.has("dateDebut") && !chantier.get("dateDebut").isNull()) {
                            String dateStr = chantier.get("dateDebut").asText();
                            try {
                                c.setDateDebut(LocalDate.parse(dateStr));
                            } catch (Exception e) {
                                logger.warn("Erreur parsing date: {}", dateStr);
                            }
                        }
                        c.setAvancement(chantier.get("avancement").asInt(0));
                        c.setBudget(chantier.get("budget").asDouble(0.0));
                        c.setStatut(chantier.get("statut").asText(""));
                        chantiersRecents.add(c);
                        count++;
                    }
                }

                JsonNode chantiersEnRetardNode = dashboard.get("chantiersEnRetard");
                if (chantiersEnRetardNode != null && chantiersEnRetardNode.isArray()) {
                    chantiersEnRetard.clear();
                    Iterator<JsonNode> iterator = chantiersEnRetardNode.elements();
                    while (iterator.hasNext()) {
                        JsonNode chantier = iterator.next();
                        ChantierResume c = new ChantierResume();
                        c.setId(chantier.get("id").asText());
                        c.setNom(chantier.get("nom").asText(""));
                        if (chantier.has("dateFinPrevue") && !chantier.get("dateFinPrevue").isNull()) {
                            String dateStr = chantier.get("dateFinPrevue").asText();
                            try {
                                c.setDateFinPrevue(LocalDate.parse(dateStr));
                            } catch (Exception e) {
                                logger.warn("Erreur parsing date: {}", dateStr);
                            }
                        }
                        c.setJoursRetard(chantier.get("joursRetard").asLong(0));
                        chantiersEnRetard.add(c);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement du dashboard chantiers", e);
        }
    }

    /**
     * Charge les métriques financières.
     */
    private void loadDashboardFinances() {
        try {
            JsonNode finances = dashboardService.getDashboardFinances(30); // 30 jours
            if (finances != null) {
                JsonNode budget = finances.get("budget");
                if (budget != null) {
                    budgetTotal = budget.get("total").asDouble(0.0);
                    budgetConsomme = budget.get("realise").asDouble(0.0);
                }
                JsonNode chiffreAffaires = finances.get("chiffreAffaires");
                if (chiffreAffaires != null) {
                    chiffreAffairesMois = chiffreAffaires.get("realise").asDouble(0.0);
                }
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement des métriques financières", e);
        }
    }

    /**
     * Charge les métriques des ressources.
     */
    private void loadDashboardRessources() {
        try {
            JsonNode ressources = dashboardService.getDashboardRessources();
            if (ressources != null) {
                JsonNode equipes = ressources.get("equipes");
                if (equipes != null && equipes.has("total")) {
                    nombreEquipes = equipes.get("total").asLong(0);
                    equipesDisponibles = equipes.get("disponibles").asLong(0);
                }
                JsonNode employes = ressources.get("employes");
                if (employes != null && employes.has("total")) {
                    nombreEmployes = employes.get("total").asLong(0);
                }
                JsonNode materiel = ressources.get("materiel");
                if (materiel != null && materiel.has("total")) {
                    nombreMateriel = materiel.get("total").asLong(0);
                    materielDisponible = materiel.get("disponible").asLong(0);
                }
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement des métriques ressources", e);
        }
    }

    /**
     * Charge les métriques de maintenance.
     */
    private void loadDashboardMaintenance() {
        try {
            JsonNode maintenance = dashboardService.getDashboardMaintenance();
            if (maintenance != null) {
                JsonNode stats = maintenance.get("statistiques");
                if (stats != null) {
                    maintenancesEnRetard = stats.has("enRetard") ? stats.get("enRetard").asLong(0) : 0;
                    maintenancesPlanifiees = stats.has("planifiees") ? stats.get("planifiees").asLong(0) : 0;
                }
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement des métriques maintenance", e);
        }
    }

    /**
     * Charge les alertes.
     */
    private void loadAlertes() {
        try {
            JsonNode alertes = dashboardService.getAlertes();
            if (alertes != null) {
                totalAlertes = alertes.get("totalAlertes").asLong(0);
                alerteCritique = alertes.get("alerteCritique").asBoolean(false);
            }
        } catch (Exception e) {
            logger.error("Erreur lors du chargement des alertes", e);
        }
    }

    /**
     * Charge le nombre de clients.
     */
    private void loadNombreClients() {
        nombreClients = dashboardService.getNombreClients();
    }

    /**
     * Charge le nombre de devis en attente.
     */
    private void loadNombreDevis() {
        nombreDevis = dashboardService.getNombreDevisEnAttente();
    }

    /**
     * Charge le nombre de factures impayées.
     */
    private void loadNombreFacturesImpayees() {
        facturesImpayees = dashboardService.getNombreFacturesImpayees();
    }

    /**
     * Rafraîchit toutes les données du dashboard.
     */
    public void rafraichir() {
        init();
    }

    /**
     * Retourne le taux de consommation du budget en pourcentage.
     * 
     * @return Le taux de consommation (0-100)
     */
    public double getTauxConsommationBudget() {
        if (budgetTotal > 0) {
            return (budgetConsomme / budgetTotal) * 100;
        }
        return 0;
    }

    /**
     * Classe interne représentant un résumé de chantier.
     */
    @lombok.Getter
    @lombok.Setter
    public static class ChantierResume implements Serializable {
        private String id;
        private String nom;
        private String client;
        private LocalDate dateDebut;
        private LocalDate dateFinPrevue;
        private int avancement;
        private double budget;
        private String statut;
        private long joursRetard;

        /**
         * Retourne la date de début formatée pour l'affichage.
         * 
         * @return La date au format dd/MM/yyyy
         */
        public String getDateDebutFormatee() {
            return dateDebut != null ? dateDebut.format(DATE_FORMATTER) : "";
        }

        /**
         * Retourne la date de fin prévue formatée pour l'affichage.
         * 
         * @return La date au format dd/MM/yyyy
         */
        public String getDateFinPrevueFormatee() {
            return dateFinPrevue != null ? dateFinPrevue.format(DATE_FORMATTER) : "";
        }
    }
}
