package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.dto.DemandeAideDTO;
import dev.lions.unionflow.client.service.DemandeAideService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.math.BigDecimal;
import java.util.logging.Logger;

@Named("demandesAideBean")
@SessionScoped
public class DemandesAideBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = Logger.getLogger(DemandesAideBean.class.getName());
    
    @Inject
    @RestClient
    private DemandeAideService demandeAideService;
    
    private List<DemandeAide> toutesLesDemandes;
    private List<DemandeAide> demandesFiltrees;
    private List<DemandeAide> demandesSelectionnees;
    private List<DemandeAide> demandesPrioritaires;
    private List<EtapeWorkflow> etapesWorkflow;
    private DemandeAide demandeSelectionnee;
    private NouvelleDemande nouvelleDemande;
    private Filtres filtres;
    private StatistiquesDemandes statistiques;
    
    @PostConstruct
    public void init() {
        initializeFiltres();
        initializeStatistiques();
        initializeDemandes();
        initializeNouvelleDemande();
        initializeDemandesPrioritaires();
        initializeEtapesWorkflow();
        appliquerFiltres();
    }
    
    private void initializeFiltres() {
        filtres = new Filtres();
        demandesSelectionnees = new ArrayList<>();
    }
    
    private void initializeStatistiques() {
        statistiques = new StatistiquesDemandes();
        try {
            List<DemandeAideDTO> demandesDTO = demandeAideService.listerToutes(0, 1000);
            statistiques.setTotalDemandes(demandesDTO.size());
            long enAttente = demandesDTO.stream().filter(d -> "EN_ATTENTE".equals(d.getStatut())).count();
            statistiques.setDemandesEnAttente((int) enAttente);
            long approuvees = demandesDTO.stream().filter(d -> "APPROUVEE".equals(d.getStatut())).count();
            statistiques.setDemandesApprouvees((int) approuvees);
            BigDecimal montantTotal = demandesDTO.stream()
                .filter(d -> d.getMontantAccorde() != null)
                .map(DemandeAideDTO::getMontantAccorde)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            statistiques.setMontantTotalAide(montantTotal.toString() + " FCFA");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du calcul des statistiques: " + e.getMessage());
            statistiques.setTotalDemandes(0);
            statistiques.setDemandesEnAttente(0);
            statistiques.setDemandesApprouvees(0);
            statistiques.setMontantTotalAide("0 FCFA");
        }
    }
    
    private void initializeEtapesWorkflow() {
        etapesWorkflow = new ArrayList<>();
        
        EtapeWorkflow enAttente = new EtapeWorkflow();
        enAttente.setLibelle("En Attente");
        enAttente.setIcon("pi-clock");
        enAttente.setCouleur("orange-500");
        enAttente.setNombre(23);
        etapesWorkflow.add(enAttente);
        
        EtapeWorkflow evaluation = new EtapeWorkflow();
        evaluation.setLibelle("Évaluation");
        evaluation.setIcon("pi-search");
        evaluation.setCouleur("blue-500");
        evaluation.setNombre(15);
        etapesWorkflow.add(evaluation);
        
        EtapeWorkflow visite = new EtapeWorkflow();
        visite.setLibelle("Visite");
        visite.setIcon("pi-home");
        visite.setCouleur("purple-500");
        visite.setNombre(8);
        etapesWorkflow.add(visite);
        
        EtapeWorkflow decision = new EtapeWorkflow();
        decision.setLibelle("Décision");
        decision.setIcon("pi-check-circle");
        decision.setCouleur("yellow-500");
        decision.setNombre(12);
        etapesWorkflow.add(decision);
        
        EtapeWorkflow versement = new EtapeWorkflow();
        versement.setLibelle("Versement");
        versement.setIcon("pi-dollar");
        versement.setCouleur("green-500");
        versement.setNombre(6);
        etapesWorkflow.add(versement);
        
        EtapeWorkflow suivi = new EtapeWorkflow();
        suivi.setLibelle("Suivi");
        suivi.setIcon("pi-chart-line");
        suivi.setCouleur("indigo-500");
        suivi.setNombre(4);
        etapesWorkflow.add(suivi);
    }
    
    private void initializeDemandes() {
        toutesLesDemandes = new ArrayList<>();
        
        try {
            List<DemandeAideDTO> demandesDTO = demandeAideService.listerToutes(0, 1000);
            for (DemandeAideDTO dto : demandesDTO) {
                DemandeAide demande = convertToDemandeAide(dto);
                toutesLesDemandes.add(demande);
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des demandes d'aide: " + e.getMessage());
        }
    }
    
    private DemandeAide convertToDemandeAide(DemandeAideDTO dto) {
        DemandeAide demande = new DemandeAide();
        demande.setId(dto.getId());
        demande.setDemandeur(dto.getDemandeur());
        demande.setTelephone(dto.getTelephone());
        demande.setEmail(dto.getEmail());
        demande.setType(dto.getType());
        demande.setStatut(dto.getStatut());
        demande.setUrgence(dto.getUrgence());
        demande.setLocalisation(dto.getLocalisation());
        demande.setMotif(dto.getMotif() != null ? dto.getMotif() : dto.getTitre());
        demande.setDescription(dto.getDescription());
        demande.setMontantDemande(dto.getMontantDemande());
        demande.setMontantAccorde(dto.getMontantAccorde());
        demande.setDateDemande(dto.getDateDemande());
        demande.setDateLimite(dto.getDateLimite());
        demande.setResponsableTraitement(dto.getResponsableTraitement());
        return demande;
    }
    
    private void initializeDemandesPrioritaires() {
        try {
            List<DemandeAideDTO> demandesDTO = demandeAideService.rechercher("EN_ATTENTE", null, "CRITIQUE", 0, 6);
            demandesPrioritaires = demandesDTO.stream()
                .map(this::convertToDemandeAide)
                .filter(d -> !d.getStatut().equals("TERMINEE") && !d.getStatut().equals("REJETEE"))
                .limit(6)
                .collect(Collectors.toList());
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des demandes prioritaires: " + e.getMessage());
            demandesPrioritaires = new ArrayList<>();
        }
    }
    
    private void initializeNouvelleDemande() {
        nouvelleDemande = new NouvelleDemande();
        nouvelleDemande.setUrgence("NORMALE");
        nouvelleDemande.setDateLimite(LocalDate.now().plusWeeks(2));
    }
    
    private void appliquerFiltres() {
        demandesFiltrees = toutesLesDemandes.stream()
                .filter(this::appliquerFiltre)
                .collect(Collectors.toList());
    }
    
    private boolean appliquerFiltre(DemandeAide demande) {
        if (filtres.getDemandeur() != null && !filtres.getDemandeur().trim().isEmpty()) {
            if (!demande.getDemandeur().toLowerCase().contains(filtres.getDemandeur().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
            if (!demande.getType().equals(filtres.getType())) {
                return false;
            }
        }
        
        if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
            if (!demande.getStatut().equals(filtres.getStatut())) {
                return false;
            }
        }
        
        if (filtres.getUrgence() != null && !filtres.getUrgence().trim().isEmpty()) {
            if (!demande.getUrgence().equals(filtres.getUrgence())) {
                return false;
            }
        }
        
        if (filtres.getLocalisation() != null && !filtres.getLocalisation().trim().isEmpty()) {
            if (!demande.getLocalisation().toLowerCase().contains(filtres.getLocalisation().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getDateDebut() != null) {
            if (demande.getDateDemande().isBefore(filtres.getDateDebut())) {
                return false;
            }
        }
        
        if (filtres.getDateFin() != null) {
            if (demande.getDateDemande().isAfter(filtres.getDateFin())) {
                return false;
            }
        }
        
        return true;
    }
    
    // Actions
    public void rechercher() {
        appliquerFiltres();
    }
    
    public void reinitialiserFiltres() {
        filtres = new Filtres();
        appliquerFiltres();
    }
    
    public void creerDemande() {
        DemandeAide nouvelleDem = new DemandeAide();
        nouvelleDem.setId(UUID.randomUUID());
        nouvelleDem.setDemandeur(nouvelleDemande.getDemandeur());
        nouvelleDem.setTelephone(nouvelleDemande.getTelephone());
        nouvelleDem.setEmail(nouvelleDemande.getEmail());
        nouvelleDem.setType(nouvelleDemande.getType());
        nouvelleDem.setLocalisation(nouvelleDemande.getLocalisation());
        nouvelleDem.setMontantDemande(nouvelleDemande.getMontantDemande());
        nouvelleDem.setUrgence(nouvelleDemande.getUrgence());
        nouvelleDem.setDateLimite(nouvelleDemande.getDateLimite());
        nouvelleDem.setMotif(nouvelleDemande.getMotif());
        nouvelleDem.setDescription(nouvelleDemande.getDescription());
        nouvelleDem.setStatut("EN_ATTENTE");
        nouvelleDem.setDateDemande(LocalDate.now());
        
        toutesLesDemandes.add(nouvelleDem);
        appliquerFiltres();
        initializeDemandesPrioritaires();
        
        LOGGER.info("Nouvelle demande d'aide créée pour: " + nouvelleDem.getDemandeur());
        initializeNouvelleDemande();
    }
    
    public void approuverDemande() {
        if (demandeSelectionnee != null) {
            demandeSelectionnee.setStatut("APPROUVEE");
            if (demandeSelectionnee.getMontantAccorde() == null) {
                demandeSelectionnee.setMontantAccorde(demandeSelectionnee.getMontantDemande().multiply(new BigDecimal("0.8")));
            }
            LOGGER.info("Demande approuvée pour: " + demandeSelectionnee.getDemandeur());
            appliquerFiltres();
            initializeDemandesPrioritaires();
        }
    }
    
    public void rejeterDemande() {
        if (demandeSelectionnee != null) {
            demandeSelectionnee.setStatut("REJETEE");
            LOGGER.info("Demande rejetée pour: " + demandeSelectionnee.getDemandeur());
            appliquerFiltres();
            initializeDemandesPrioritaires();
        }
    }
    
    public String voirHistorique() {
        return "/pages/admin/demandes/historique?id=" + demandeSelectionnee.getId() + "&faces-redirect=true";
    }
    
    public void envoyerNotification() {
        LOGGER.info("Notification envoyée pour la demande de: " + demandeSelectionnee.getDemandeur());
    }
    
    public void dupliquerDemande() {
        if (demandeSelectionnee != null) {
            DemandeAide copie = new DemandeAide();
            copie.setId(UUID.randomUUID());
            copie.setDemandeur(demandeSelectionnee.getDemandeur());
            copie.setTelephone(demandeSelectionnee.getTelephone());
            copie.setEmail(demandeSelectionnee.getEmail());
            copie.setType(demandeSelectionnee.getType());
            copie.setLocalisation(demandeSelectionnee.getLocalisation());
            copie.setMontantDemande(demandeSelectionnee.getMontantDemande());
            copie.setUrgence(demandeSelectionnee.getUrgence());
            copie.setMotif(demandeSelectionnee.getMotif() + " (Copie)");
            copie.setDescription(demandeSelectionnee.getDescription());
            copie.setStatut("EN_ATTENTE");
            copie.setDateDemande(LocalDate.now());
            
            toutesLesDemandes.add(copie);
            appliquerFiltres();
            LOGGER.info("Demande dupliquée pour: " + copie.getDemandeur());
        }
    }
    
    public void exporterDemandes() {
        LOGGER.info("Export de " + demandesFiltrees.size() + " demandes d'aide");
    }
    
    // Getters et Setters
    public List<DemandeAide> getToutesLesDemandes() { return toutesLesDemandes; }
    public void setToutesLesDemandes(List<DemandeAide> toutesLesDemandes) { this.toutesLesDemandes = toutesLesDemandes; }
    
    public List<DemandeAide> getDemandesFiltrees() { return demandesFiltrees; }
    public void setDemandesFiltrees(List<DemandeAide> demandesFiltrees) { this.demandesFiltrees = demandesFiltrees; }
    
    public List<DemandeAide> getDemandesSelectionnees() { return demandesSelectionnees; }
    public void setDemandesSelectionnees(List<DemandeAide> demandesSelectionnees) { this.demandesSelectionnees = demandesSelectionnees; }
    
    public List<DemandeAide> getDemandesPrioritaires() { return demandesPrioritaires; }
    public void setDemandesPrioritaires(List<DemandeAide> demandesPrioritaires) { this.demandesPrioritaires = demandesPrioritaires; }
    
    public List<EtapeWorkflow> getEtapesWorkflow() { return etapesWorkflow; }
    public void setEtapesWorkflow(List<EtapeWorkflow> etapesWorkflow) { this.etapesWorkflow = etapesWorkflow; }
    
    public DemandeAide getDemandeSelectionnee() { return demandeSelectionnee; }
    public void setDemandeSelectionnee(DemandeAide demandeSelectionnee) { this.demandeSelectionnee = demandeSelectionnee; }
    
    public NouvelleDemande getNouvelleDemande() { return nouvelleDemande; }
    public void setNouvelleDemande(NouvelleDemande nouvelleDemande) { this.nouvelleDemande = nouvelleDemande; }
    
    public Filtres getFiltres() { return filtres; }
    public void setFiltres(Filtres filtres) { this.filtres = filtres; }
    
    public StatistiquesDemandes getStatistiques() { return statistiques; }
    public void setStatistiques(StatistiquesDemandes statistiques) { this.statistiques = statistiques; }
    
    // Classes internes
    public static class DemandeAide {
        private UUID id;
        private String demandeur;
        private String telephone;
        private String email;
        private String type;
        private String statut;
        private String urgence;
        private String localisation;
        private String motif;
        private String description;
        private BigDecimal montantDemande;
        private BigDecimal montantAccorde;
        private LocalDate dateDemande;
        private LocalDate dateLimite;
        private String responsableTraitement;
        
        // Getters et setters
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getDemandeur() { return demandeur; }
        public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
        
        public String getTelephone() { return telephone; }
        public void setTelephone(String telephone) { this.telephone = telephone; }
        
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getUrgence() { return urgence; }
        public void setUrgence(String urgence) { this.urgence = urgence; }
        
        public String getLocalisation() { return localisation; }
        public void setLocalisation(String localisation) { this.localisation = localisation; }
        
        public String getMotif() { return motif; }
        public void setMotif(String motif) { this.motif = motif; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public BigDecimal getMontantDemande() { return montantDemande; }
        public void setMontantDemande(BigDecimal montantDemande) { this.montantDemande = montantDemande; }
        
        public BigDecimal getMontantAccorde() { return montantAccorde; }
        public void setMontantAccorde(BigDecimal montantAccorde) { this.montantAccorde = montantAccorde; }
        
        public LocalDate getDateDemande() { return dateDemande; }
        public void setDateDemande(LocalDate dateDemande) { this.dateDemande = dateDemande; }
        
        public LocalDate getDateLimite() { return dateLimite; }
        public void setDateLimite(LocalDate dateLimite) { this.dateLimite = dateLimite; }
        
        public String getResponsableTraitement() { return responsableTraitement; }
        public void setResponsableTraitement(String responsableTraitement) { this.responsableTraitement = responsableTraitement; }
        
        // Propriétés dérivées
        public String getTypeLibelle() {
            return switch (type) {
                case "AIDE_MEDICALE" -> "Aide Médicale";
                case "AIDE_ALIMENTAIRE" -> "Aide Alimentaire";
                case "AIDE_EDUCATIVE" -> "Aide Éducative";
                case "AIDE_LOGEMENT" -> "Aide Logement";
                case "AIDE_URGENCE" -> "Aide d'Urgence";
                default -> type;
            };
        }
        
        public String getTypeSeverity() {
            return switch (type) {
                case "AIDE_MEDICALE" -> "danger";
                case "AIDE_ALIMENTAIRE" -> "warning";
                case "AIDE_EDUCATIVE" -> "info";
                case "AIDE_LOGEMENT" -> "secondary";
                case "AIDE_URGENCE" -> "primary";
                default -> "primary";
            };
        }
        
        public String getTypeIcon() {
            return switch (type) {
                case "AIDE_MEDICALE" -> "pi-heart";
                case "AIDE_ALIMENTAIRE" -> "pi-shopping-cart";
                case "AIDE_EDUCATIVE" -> "pi-book";
                case "AIDE_LOGEMENT" -> "pi-home";
                case "AIDE_URGENCE" -> "pi-exclamation-triangle";
                default -> "pi-question";
            };
        }
        
        public String getStatutLibelle() {
            return switch (statut) {
                case "EN_ATTENTE" -> "En Attente";
                case "EN_EVALUATION" -> "En Évaluation";
                case "APPROUVEE" -> "Approuvée";
                case "REJETEE" -> "Rejetée";
                case "EN_COURS" -> "En Cours";
                case "TERMINEE" -> "Terminée";
                default -> statut;
            };
        }
        
        public String getStatutSeverity() {
            return switch (statut) {
                case "EN_ATTENTE" -> "warning";
                case "EN_EVALUATION" -> "info";
                case "APPROUVEE" -> "success";
                case "REJETEE" -> "danger";
                case "EN_COURS" -> "primary";
                case "TERMINEE" -> "secondary";
                default -> "secondary";
            };
        }
        
        public String getStatutIcon() {
            return switch (statut) {
                case "EN_ATTENTE" -> "pi-clock";
                case "EN_EVALUATION" -> "pi-search";
                case "APPROUVEE" -> "pi-check";
                case "REJETEE" -> "pi-times";
                case "EN_COURS" -> "pi-play";
                case "TERMINEE" -> "pi-check-circle";
                default -> "pi-circle";
            };
        }
        
        public String getUrgenceSeverity() {
            return switch (urgence) {
                case "FAIBLE" -> "secondary";
                case "NORMALE" -> "info";
                case "ELEVEE" -> "warning";
                case "CRITIQUE" -> "danger";
                default -> "primary";
            };
        }
        
        public String getDateDemandeFormatee() {
            if (dateDemande == null) return "";
            return dateDemande.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
        }
        
        public String getMontantDemandeFormatte() {
            if (montantDemande == null) return "";
            return String.format("%,.0f FCFA", montantDemande);
        }
        
        public String getMontantAccordeFormatte() {
            if (montantAccorde == null) return "";
            return String.format("%,.0f FCFA", montantAccorde);
        }
        
        public long getJoursDepuisDemande() {
            if (dateDemande == null) return 0;
            return ChronoUnit.DAYS.between(dateDemande, LocalDate.now());
        }
    }
    
    public static class NouvelleDemande {
        private String demandeur;
        private String telephone;
        private String email;
        private String type;
        private String localisation;
        private BigDecimal montantDemande;
        private String urgence;
        private LocalDate dateLimite;
        private String motif;
        private String description;
        
        // Getters et setters
        public String getDemandeur() { return demandeur; }
        public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
        
        public String getTelephone() { return telephone; }
        public void setTelephone(String telephone) { this.telephone = telephone; }
        
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getLocalisation() { return localisation; }
        public void setLocalisation(String localisation) { this.localisation = localisation; }
        
        public BigDecimal getMontantDemande() { return montantDemande; }
        public void setMontantDemande(BigDecimal montantDemande) { this.montantDemande = montantDemande; }
        
        public String getUrgence() { return urgence; }
        public void setUrgence(String urgence) { this.urgence = urgence; }
        
        public LocalDate getDateLimite() { return dateLimite; }
        public void setDateLimite(LocalDate dateLimite) { this.dateLimite = dateLimite; }
        
        public String getMotif() { return motif; }
        public void setMotif(String motif) { this.motif = motif; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
    }
    
    public static class Filtres {
        private String demandeur;
        private String type;
        private String statut;
        private String urgence;
        private String localisation;
        private LocalDate dateDebut;
        private LocalDate dateFin;
        
        // Getters et setters
        public String getDemandeur() { return demandeur; }
        public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getUrgence() { return urgence; }
        public void setUrgence(String urgence) { this.urgence = urgence; }
        
        public String getLocalisation() { return localisation; }
        public void setLocalisation(String localisation) { this.localisation = localisation; }
        
        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 static class StatistiquesDemandes {
        private int totalDemandes;
        private int demandesEnAttente;
        private int demandesApprouvees;
        private String montantTotalAide;
        
        // Getters et setters
        public int getTotalDemandes() { return totalDemandes; }
        public void setTotalDemandes(int totalDemandes) { this.totalDemandes = totalDemandes; }
        
        public int getDemandesEnAttente() { return demandesEnAttente; }
        public void setDemandesEnAttente(int demandesEnAttente) { this.demandesEnAttente = demandesEnAttente; }
        
        public int getDemandesApprouvees() { return demandesApprouvees; }
        public void setDemandesApprouvees(int demandesApprouvees) { this.demandesApprouvees = demandesApprouvees; }
        
        public String getMontantTotalAide() { return montantTotalAide; }
        public void setMontantTotalAide(String montantTotalAide) { this.montantTotalAide = montantTotalAide; }
    }
    
    public static class EtapeWorkflow {
        private String libelle;
        private String icon;
        private String couleur;
        private int nombre;
        
        // Getters et setters
        public String getLibelle() { return libelle; }
        public void setLibelle(String libelle) { this.libelle = libelle; }
        
        public String getIcon() { return icon; }
        public void setIcon(String icon) { this.icon = icon; }
        
        public String getCouleur() { return couleur; }
        public void setCouleur(String couleur) { this.couleur = couleur; }
        
        public int getNombre() { return nombre; }
        public void setNombre(int nombre) { this.nombre = nombre; }
    }
}