package dev.lions.unionflow.client.view;

import dev.lions.unionflow.server.api.dto.solidarite.response.DemandeAideResponse;
import dev.lions.unionflow.client.service.DemandeAideService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.jboss.logging.Logger;

@Named("demandeBean")
@SessionScoped
public class DemandesBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(DemandesBean.class);

    @Inject
    @RestClient
    private DemandeAideService demandeAideService;
    
    private List<Demande> demandes;
    private List<Demande> selectedDemandes;
    private List<Demande> demandesUrgentes;
    private List<Demande> dernieresDemandes;
    private List<Gestionnaire> gestionnairesDisponibles;
    private Membre membreDemandeur;
    private NouvelleDemande nouvelleDemande;
    private Demande demandeSelectionnee;
    
    // Filtres
    private String searchFilter;
    private String statutFilter;
    private String typeFilter;
    private String prioriteFilter;
    private LocalDate dateFilter;
    
    // Assignation en lot
    private UUID gestionnaireAssignation;
    private String commentaireAssignation;
    
    // Statistiques
    private int enAttente = 0;
    private int urgentes = 0;
    private int traitees = 0;
    private int delaiMoyenTraitement = 0;
    
    @PostConstruct
    public void init() {
        initializeDemandes();
        initializeGestionnaires();
        initializeNouvelleDemande();
        calculerStatistiques();
        selectedDemandes = new ArrayList<>();
    }
    
    private void initializeDemandes() {
        demandes = new ArrayList<>();
        try {
            List<DemandeAideResponse> dtos = demandeAideService.listerToutes(0, 1000);
            if (dtos != null) {
                for (DemandeAideResponse dto : dtos) {
                    demandes.add(mapToDemande(dto));
                }
            }
            LOG.infof("Demandes chargées: %d", demandes.size());
        } catch (Exception e) {
            LOG.warnf(e, "Impossible de charger les demandes: %s", e.getMessage());
        }
    }

    private Demande mapToDemande(DemandeAideResponse dto) {
        Demande d = new Demande();
        d.setId(dto.getId());
        d.setReference(dto.getNumeroReference());
        d.setObjet(dto.getTitre());
        d.setType(dto.getTypeAide() != null ? dto.getTypeAide().name() : null);
        d.setStatut(dto.getStatut() != null ? dto.getStatut().name() : null);
        d.setPriorite(dto.getPriorite() != null ? dto.getPriorite().name() : null);
        d.setNomDemandeur(dto.getNomDemandeur());
        d.setTelephoneDemandeur(null); // Champ non disponible dans DemandeAideResponse
        d.setDateDepot(dto.getDateSoumission() != null ? dto.getDateSoumission().toLocalDate() : null);
        d.setDateEcheance(dto.getDateLimiteTraitement() != null ? dto.getDateLimiteTraitement().toLocalDate() : null);
        d.setDemandeur(dto.getNomDemandeur());
        return d;
    }
    
    private void calculerStatistiques() {
        if (demandes == null || demandes.isEmpty()) {
            enAttente = 0;
            urgentes = 0;
            traitees = 0;
            delaiMoyenTraitement = 0;
            return;
        }
        
        // Calculer depuis les données réelles
        enAttente = (int) demandes.stream()
                .filter(d -> "EN_ATTENTE".equals(d.getStatut()))
                .count();
        
        urgentes = (int) demandes.stream()
                .filter(d -> "URGENTE".equals(d.getPriorite()))
                .count();
        
        traitees = (int) demandes.stream()
                .filter(d -> "APPROUVEE".equals(d.getStatut()) || "REJETEE".equals(d.getStatut()))
                .count();
        
        // Calculer le délai moyen de traitement
        long totalJours = demandes.stream()
                .filter(d -> d.getDateDepot() != null && "APPROUVEE".equals(d.getStatut()))
                .mapToLong(d -> ChronoUnit.DAYS.between(d.getDateDepot(), LocalDate.now()))
                .sum();
        long countTraitees = demandes.stream()
                .filter(d -> d.getDateDepot() != null && "APPROUVEE".equals(d.getStatut()))
                .count();
        delaiMoyenTraitement = countTraitees > 0 ? (int) (totalJours / countTraitees) : 0;
        
        // Initialiser les sous-listes
        demandesUrgentes = demandes.stream()
                .filter(d -> "URGENTE".equals(d.getPriorite()) || "EN_ATTENTE".equals(d.getStatut()))
                .limit(3)
                .collect(Collectors.toList());
                
        dernieresDemandes = demandes.stream()
                .sorted((d1, d2) -> {
                    if (d1.getDateDepot() == null) return 1;
                    if (d2.getDateDepot() == null) return -1;
                    return d2.getDateDepot().compareTo(d1.getDateDepot());
                })
                .limit(4)
                .collect(Collectors.toList());
    }
    
    private void initializeGestionnaires() {
        gestionnairesDisponibles = new ArrayList<>();
        gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000500"), "Marie Gestionnaire"));
        gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000600"), "Paul Superviseur"));
        gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000700"), "Fatou Responsable"));
    }
    
    private void initializeNouvelleDemande() {
        nouvelleDemande = new NouvelleDemande();
        nouvelleDemande.setPriorite("NORMALE");
        nouvelleDemande.setDateEcheance(LocalDate.now().plusWeeks(2));
    }
    
    public List<Membre> rechercherMembres(String query) {
        List<Membre> resultats = new ArrayList<>();
        
        String[] noms = {"Marie Kouassi", "Paul Traoré", "Fatou Sanogo", "Jean Ouattara", "Aissata Koné"};
        for (int i = 0; i < noms.length; i++) {
            if (noms[i].toLowerCase().contains(query.toLowerCase())) {
                Membre membre = new Membre();
                membre.setId(UUID.fromString(String.format("00000000-0000-0000-0000-%012d", i + 1)));
                membre.setNomComplet(noms[i]);
                membre.setNumeroMembre("M" + String.format("%06d", 1000 + i));
                resultats.add(membre);
            }
        }
        
        return resultats;
    }
    
    // Actions
    public void voirDemande(Demande demande) {
        this.demandeSelectionnee = demande;
        LOG.infof("Voir demande: %s", demande.getObjet());
    }
    
    public void traiterDemande(Demande demande) {
        demande.setStatut("EN_COURS");
        LOG.infof("Traitement demande: %s", demande.getObjet());
    }
    
    public void approuverDemande(Demande demande) {
        demande.setStatut("APPROUVEE");
        LOG.infof("Demande approuvée: %s", demande.getObjet());
    }
    
    public void rejeterDemande(Demande demande) {
        demande.setStatut("REJETEE");
        LOG.infof("Demande rejetée: %s", demande.getObjet());
    }
    
    public void assignerDemande(Demande demande) {
        LOG.infof("Assigner demande: %s", demande.getObjet());
    }
    
    public void voirPiecesJointes(Demande demande) {
        LOG.infof("Voir pièces jointes: %s", demande.getObjet());
    }
    
    public void creerDemande() {
        LOG.infof("Créer nouvelle demande: %s", nouvelleDemande.getObjet());
        initializeNouvelleDemande();
    }
    
    public void effectuerAssignationLot() {
        LOG.infof("Assignation en lot à gestionnaire ID: %s", gestionnaireAssignation);
    }
    
    public void marquerTraitees() {
        selectedDemandes.forEach(d -> d.setStatut("TRAITEE"));
        LOG.infof("Marquées comme traitées: %d", selectedDemandes.size());
    }
    
    public void exporterSelection() {
        LOG.infof("Export de %d demandes", selectedDemandes.size());
    }
    
    public void exporterDemandes() {
        LOG.info("Export de toutes les demandes");
    }
    
    public void actualiser() {
        LOG.info("Actualisation des données");
        initializeDemandes();
        calculerStatistiques();
    }
    
    public void filtrerUrgentes() {
        LOG.info("Filtrer les demandes urgentes");
    }
    
    // Getters et Setters
    public List<Demande> getDemandes() { return demandes; }
    public void setDemandes(List<Demande> demandes) { this.demandes = demandes; }
    
    public List<Demande> getSelectedDemandes() { return selectedDemandes; }
    public void setSelectedDemandes(List<Demande> selectedDemandes) { this.selectedDemandes = selectedDemandes; }
    
    public List<Demande> getDemandesUrgentes() { return demandesUrgentes; }
    public void setDemandesUrgentes(List<Demande> demandesUrgentes) { this.demandesUrgentes = demandesUrgentes; }
    
    public List<Demande> getDernieresDemandes() { return dernieresDemandes; }
    public void setDernieresDemandes(List<Demande> dernieresDemandes) { this.dernieresDemandes = dernieresDemandes; }
    
    public List<Gestionnaire> getGestionnairesDisponibles() { return gestionnairesDisponibles; }
    public void setGestionnairesDisponibles(List<Gestionnaire> gestionnairesDisponibles) { this.gestionnairesDisponibles = gestionnairesDisponibles; }
    
    public Membre getMembreDemandeur() { return membreDemandeur; }
    public void setMembreDemandeur(Membre membreDemandeur) { this.membreDemandeur = membreDemandeur; }
    
    public NouvelleDemande getNouvelleDemande() { return nouvelleDemande; }
    public void setNouvelleDemande(NouvelleDemande nouvelleDemande) { this.nouvelleDemande = nouvelleDemande; }
    
    public String getSearchFilter() { return searchFilter; }
    public void setSearchFilter(String searchFilter) { this.searchFilter = searchFilter; }
    
    public String getStatutFilter() { return statutFilter; }
    public void setStatutFilter(String statutFilter) { this.statutFilter = statutFilter; }
    
    public String getTypeFilter() { return typeFilter; }
    public void setTypeFilter(String typeFilter) { this.typeFilter = typeFilter; }
    
    public String getPrioriteFilter() { return prioriteFilter; }
    public void setPrioriteFilter(String prioriteFilter) { this.prioriteFilter = prioriteFilter; }
    
    public LocalDate getDateFilter() { return dateFilter; }
    public void setDateFilter(LocalDate dateFilter) { this.dateFilter = dateFilter; }
    
    public UUID getGestionnaireAssignation() { return gestionnaireAssignation; }
    public void setGestionnaireAssignation(UUID gestionnaireAssignation) { this.gestionnaireAssignation = gestionnaireAssignation; }
    
    public String getCommentaireAssignation() { return commentaireAssignation; }
    public void setCommentaireAssignation(String commentaireAssignation) { this.commentaireAssignation = commentaireAssignation; }
    
    public int getEnAttente() { return enAttente; }
    public void setEnAttente(int enAttente) { this.enAttente = enAttente; }
    
    public int getUrgentes() { return urgentes; }
    public void setUrgentes(int urgentes) { this.urgentes = urgentes; }
    
    public int getTraitees() { return traitees; }
    public void setTraitees(int traitees) { this.traitees = traitees; }
    
    public int getDelaiMoyenTraitement() { return delaiMoyenTraitement; }
    public void setDelaiMoyenTraitement(int delaiMoyenTraitement) { this.delaiMoyenTraitement = delaiMoyenTraitement; }
    
    public Demande getDemandeSelectionnee() { return demandeSelectionnee; }
    public void setDemandeSelectionnee(Demande demandeSelectionnee) { this.demandeSelectionnee = demandeSelectionnee; }
    
    // Classes internes
    public static class Demande {
        private UUID id;
        private String reference;
        private String objet;
        private String type;
        private String statut;
        private String priorite;
        private String nomDemandeur;
        private String numeroMembre;
        private String telephoneDemandeur;
        private LocalDate dateDepot;
        private LocalDate dateEcheance;
        private String heureDepot;
        private String assigneA;
        private String demandeur;
        private boolean hasPiecesJointes = false;
        
        // Getters et setters
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getReference() { return reference; }
        public void setReference(String reference) { this.reference = reference; }
        
        public String getObjet() { return objet; }
        public void setObjet(String objet) { this.objet = objet; }
        
        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 getPriorite() { return priorite; }
        public void setPriorite(String priorite) { this.priorite = priorite; }
        
        public String getNomDemandeur() { return nomDemandeur; }
        public void setNomDemandeur(String nomDemandeur) { this.nomDemandeur = nomDemandeur; }
        
        public String getNumeroMembre() { return numeroMembre; }
        public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
        
        public String getTelephoneDemandeur() { return telephoneDemandeur; }
        public void setTelephoneDemandeur(String telephoneDemandeur) { this.telephoneDemandeur = telephoneDemandeur; }
        
        public LocalDate getDateDepot() { return dateDepot; }
        public void setDateDepot(LocalDate dateDepot) { this.dateDepot = dateDepot; }
        
        public LocalDate getDateEcheance() { return dateEcheance; }
        public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
        
        public String getHeureDepot() { return heureDepot; }
        public void setHeureDepot(String heureDepot) { this.heureDepot = heureDepot; }
        
        public String getAssigneA() { return assigneA; }
        public void setAssigneA(String assigneA) { this.assigneA = assigneA; }
        
        public String getDemandeur() { return demandeur != null ? demandeur : nomDemandeur; }
        public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
        
        public boolean isHasPiecesJointes() { return hasPiecesJointes; }
        public void setHasPiecesJointes(boolean hasPiecesJointes) { this.hasPiecesJointes = hasPiecesJointes; }
        
        // Propriétés dérivées
        public String getNomCompletDemandeur() { return nomDemandeur; }
        public String getInitialesDemandeur() {
            if (nomDemandeur == null) return "??";
            String[] parts = nomDemandeur.split(" ");
            return parts.length >= 2 ? parts[0].substring(0,1) + parts[1].substring(0,1) : nomDemandeur.substring(0, Math.min(2, nomDemandeur.length()));
        }
        
        public String getTypeIcon() {
            return switch (type) {
                case "ADHESION" -> "pi-user-plus";
                case "AIDE_FINANCIERE" -> "pi-money-bill";
                case "CERTIFICAT" -> "pi-file";
                case "MUTATION" -> "pi-arrow-right-arrow-left";
                case "RECLAMATION" -> "pi-exclamation-triangle";
                default -> "pi-question";
            };
        }
        
        public String getTypeColorClass() {
            return switch (type) {
                case "ADHESION" -> "bg-blue-500";
                case "AIDE_FINANCIERE" -> "bg-green-500";
                case "CERTIFICAT" -> "bg-purple-500";
                case "MUTATION" -> "bg-orange-500";
                case "RECLAMATION" -> "bg-red-500";
                default -> "bg-gray-500";
            };
        }
        
        public String getStatutSeverity() {
            return switch (statut) {
                case "EN_ATTENTE" -> "warning";
                case "EN_COURS" -> "info";
                case "APPROUVEE" -> "success";
                case "REJETEE" -> "danger";
                case "URGENTE" -> "danger";
                default -> "secondary";
            };
        }
        
        public String getStatutIcon() {
            return switch (statut) {
                case "EN_ATTENTE" -> "pi-clock";
                case "EN_COURS" -> "pi-spin pi-spinner";
                case "APPROUVEE" -> "pi-check";
                case "REJETEE" -> "pi-times";
                case "URGENTE" -> "pi-exclamation-triangle";
                default -> "pi-circle";
            };
        }
        
        public String getPrioriteSeverity() {
            return switch (priorite) {
                case "URGENTE" -> "danger";
                case "HAUTE" -> "warning";
                case "NORMALE" -> "info";
                case "BASSE" -> "secondary";
                default -> "primary";
            };
        }
        
        public String getPrioriteIcon() {
            return switch (priorite) {
                case "URGENTE" -> "pi-exclamation-triangle";
                case "HAUTE" -> "pi-arrow-up";
                case "NORMALE" -> "pi-minus";
                case "BASSE" -> "pi-arrow-down";
                default -> "pi-circle";
            };
        }
        
        public String getDateDepotRelative() {
            if (dateDepot == null) return "";
            long jours = ChronoUnit.DAYS.between(dateDepot, LocalDate.now());
            if (jours == 0) return "aujourd'hui";
            if (jours == 1) return "hier";
            return "il y a " + jours + " jours";
        }
        
        public String getEcheanceClass() {
            if (dateEcheance == null) return "";
            long jours = ChronoUnit.DAYS.between(LocalDate.now(), dateEcheance);
            if (jours < 0) return "text-red-500 font-bold";
            if (jours <= 3) return "text-orange-500 font-bold";
            return "text-600";
        }
    }
    
    public static class Membre {
        private UUID id;
        private String nomComplet;
        private String numeroMembre;
        
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getNomComplet() { return nomComplet; }
        public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
        
        public String getNumeroMembre() { return numeroMembre; }
        public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
        
        public String getInitiales() {
            if (nomComplet == null) return "??";
            String[] parts = nomComplet.split(" ");
            return parts.length >= 2 ? parts[0].substring(0,1) + parts[1].substring(0,1) : nomComplet.substring(0, Math.min(2, nomComplet.length()));
        }
    }
    
    public static class NouvelleDemande {
        private String objet;
        private String type;
        private String priorite;
        private String description;
        private LocalDate dateEcheance;
        private UUID assigneA;
        
        public String getObjet() { return objet; }
        public void setObjet(String objet) { this.objet = objet; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getPriorite() { return priorite; }
        public void setPriorite(String priorite) { this.priorite = priorite; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public LocalDate getDateEcheance() { return dateEcheance; }
        public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
        
        public UUID getAssigneA() { return assigneA; }
        public void setAssigneA(UUID assigneA) { this.assigneA = assigneA; }
    }
    
    public static class Gestionnaire {
        private UUID id;
        private String nom;
        
        public Gestionnaire() {}
        
        public Gestionnaire(UUID id, String nom) {
            this.id = id;
            this.nom = nom;
        }
        
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
    }
}
