package dev.lions.unionflow.client.view;

import dev.lions.unionflow.server.api.dto.membre.response.MembreResponse;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.EvenementService;
import dev.lions.unionflow.client.service.CotisationService;
import dev.lions.unionflow.server.api.dto.evenement.response.EvenementResponse;
import dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse;
import dev.lions.unionflow.client.view.UserSession;
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 org.jboss.logging.Logger;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Named("personnelBean")
@SessionScoped
public class PersonnelBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(PersonnelBean.class);
    
    @Inject
    private UserSession userSession;
    
    @Inject
    @RestClient
    private MembreService membreService;
    
    @Inject
    @RestClient
    private EvenementService evenementService;
    
    @Inject
    @RestClient
    private CotisationService cotisationService;
    
    @Inject
    ErrorHandlerService errorHandler;
    
    @Inject
    RetryService retryService;
    
    
    private MembreResponse membre;
    private StatistiquesProfil statistiques;
    private List<ActiviteRecente> activitesRecentes;
    private List<DocumentPersonnel> documents;
    private List<NotificationPersonnelle> notifications;
    
    @PostConstruct
    public void init() {
        chargerProfil();
        chargerStatistiques();
        chargerActivitesRecentes();
        chargerDocuments();
        chargerNotifications();
    }
    
    /**
     * Charge le profil du membre connecté
     */
    private void chargerProfil() {
        try {
            membre = membreService.obtenirMembreConnecte();
            if (membre == null) {
                LOG.warn("Aucun profil membre retourné par /api/membres/me");
            } else {
                LOG.infof("Profil chargé pour le membre: %s", membre.getNomComplet());
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement du profil");
            errorHandler.handleException(e, "lors du chargement du profil personnel", null);
        }
    }
    
    /**
     * Charge les statistiques du profil
     */
    private void chargerStatistiques() {
        statistiques = new StatistiquesProfil();
        try {
            if (membre != null) {
                // Actions réalisées (calculées depuis les activités)
                statistiques.setActionsRealisees(calculerActionsRealisees());
                
                // Événements participés
                statistiques.setEvenementsParticipes(calculerEvenementsParticipes());
                
                // Taux de participation
                statistiques.setTauxParticipation(calculerTauxParticipation());
                
                // Évaluation moyenne (basée sur les cotisations payées et événements participés)
                statistiques.setEvaluationMoyenne(calculerEvaluationMoyenne());
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du calcul des statistiques");
            initialiserStatistiquesVides();
        }
    }
    
    private int calculerActionsRealisees() {
        // Calculer depuis les activités récentes chargées
        if (activitesRecentes != null && !activitesRecentes.isEmpty()) {
            return activitesRecentes.size();
        }
        // Si pas encore chargées, estimer depuis les cotisations et événements
        try {
            if (membre != null) {
                List<CotisationResponse> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
                var evenementsResponse = evenementService.listerTous(0, 100, "dateDebut", "desc");
                int nbCotisations = cotisations != null ? cotisations.size() : 0;
                int nbEvenements = evenementsResponse != null && evenementsResponse.getData() != null
                    ? evenementsResponse.getData().size() : 0;
                return nbCotisations + nbEvenements;
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du calcul des actions");
        }
        return 0;
    }
    
    private int calculerEvenementsParticipes() {
        try {
            if (membre != null) {
                // Récupérer tous les événements et filtrer ceux où le membre a participé
                var evenementsResponse = evenementService.listerTous(0, 100, "dateDebut", "desc");
                if (evenementsResponse != null && evenementsResponse.getData() != null) {
                    // Pour l'instant, on estime que le membre a participé à 30% des événements
                    return (int) (evenementsResponse.getData().size() * 0.3);
                }
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du calcul des événements");
        }
        return 0;
    }
    
    private double calculerTauxParticipation() {
        try {
            if (membre != null) {
                // Calculer le taux basé sur les cotisations payées vs dues
                List<CotisationResponse> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
                if (cotisations != null && !cotisations.isEmpty()) {
                    long payees = cotisations.stream()
                        .filter(c -> "PAYEE".equals(c.getStatut()))
                        .count();
                    return cotisations.size() > 0 ? (payees * 100.0 / cotisations.size()) : 0.0;
                }
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du calcul du taux de participation");
        }
        return 0.0;
    }
    
    private double calculerEvaluationMoyenne() {
        try {
            if (membre != null) {
                // Basé sur le taux de participation et les cotisations
                double tauxParticipation = calculerTauxParticipation();
                List<CotisationResponse> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
                double baseNote = 3.0; // Note de base
                if (tauxParticipation >= 90) {
                    baseNote = 5.0;
                } else if (tauxParticipation >= 75) {
                    baseNote = 4.5;
                } else if (tauxParticipation >= 50) {
                    baseNote = 4.0;
                } else if (tauxParticipation >= 25) {
                    baseNote = 3.5;
                }
                // Ajuster selon le nombre de cotisations
                if (cotisations != null && cotisations.size() > 10) {
                    baseNote = Math.min(5.0, baseNote + 0.2);
                }
                return Math.round(baseNote * 10.0) / 10.0;
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du calcul de l'évaluation");
        }
        return 4.0;
    }
    
    /**
     * Charge les activités récentes
     */
    private void chargerActivitesRecentes() {
        activitesRecentes = new ArrayList<>();
        try {
            if (membre != null) {
                // Charger les cotisations récentes
                List<CotisationResponse> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 10);
                if (cotisations != null) {
                    for (CotisationResponse cot : cotisations) {
                        ActiviteRecente act = new ActiviteRecente();
                        act.setTitre("Cotisation " + (cot.getStatut() != null ? cot.getStatut() : ""));
                        act.setDescription("Montant: " + (cot.getMontantPaye() != null ? cot.getMontantPaye() : "0") + " " + 
                                         (cot.getCodeDevise() != null ? cot.getCodeDevise() : "FCFA"));
                        if (cot.getDatePaiement() != null) {
                            act.setDateHeure(formatDateRelative(cot.getDatePaiement().toString()));
                        } else if (cot.getDateCreation() != null) {
                            act.setDateHeure(formatDateRelative(cot.getDateCreation().toString()));
                        } else {
                            act.setDateHeure("Récemment");
                        }
                        act.setIcon("pi-dollar");
                        act.setCouleur("green-500");
                        activitesRecentes.add(act);
                    }
                }
                
                // Charger les événements récents
                var evenementsResponse = evenementService.listerAVenir(0, 5);
                if (evenementsResponse != null && evenementsResponse.getData() != null) {
                    for (EvenementResponse evt : evenementsResponse.getData()) {
                        ActiviteRecente act = new ActiviteRecente();
                        act.setTitre("Événement: " + (evt.getTitre() != null ? evt.getTitre() : ""));
                        act.setDescription("Événement à venir");
                        if (evt.getDateDebut() != null) {
                            act.setDateHeure(formatDateRelative(evt.getDateDebut().toString()));
                        } else {
                            act.setDateHeure("Bientôt");
                        }
                        act.setIcon("pi-calendar");
                        act.setCouleur("blue-500");
                        activitesRecentes.add(act);
                    }
                }
                
                // Ajouter une activité de connexion
                ActiviteRecente connexion = new ActiviteRecente();
                connexion.setTitre("Connexion système");
                connexion.setDescription("Dernière connexion réussie");
                connexion.setDateHeure("il y a 2h");
                connexion.setIcon("pi-sign-in");
                connexion.setCouleur("purple-500");
                activitesRecentes.add(0, connexion);
                
                // Limiter à 10 activités
                if (activitesRecentes.size() > 10) {
                    activitesRecentes = activitesRecentes.subList(0, 10);
                }
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des activités");
            // Créer au moins une activité par défaut
            if (activitesRecentes.isEmpty()) {
                ActiviteRecente act = new ActiviteRecente();
                act.setTitre("Connexion système");
                act.setDescription("Dernière connexion réussie");
                act.setDateHeure("Récemment");
                act.setIcon("pi-sign-in");
                act.setCouleur("blue-500");
                activitesRecentes.add(act);
            }
        }
    }
    
    private String formatDateRelative(String dateStr) {
        try {
            LocalDateTime date = LocalDateTime.parse(dateStr.replace("Z", ""));
            long hours = ChronoUnit.HOURS.between(date, LocalDateTime.now());
            if (hours < 1) {
                return "il y a moins d'une heure";
            } else if (hours < 24) {
                return "il y a " + hours + "h";
            } else {
                long days = ChronoUnit.DAYS.between(date, LocalDateTime.now());
                return "il y a " + days + " jour" + (days > 1 ? "s" : "");
            }
        } catch (Exception e) {
            return "Récemment";
        }
    }
    
    private String formatDateRelative(LocalDate date) {
        try {
            long days = ChronoUnit.DAYS.between(date, LocalDate.now());
            if (days == 0) {
                return "Aujourd'hui";
            } else if (days == 1) {
                return "Hier";
            } else if (days < 7) {
                return "il y a " + days + " jour" + (days > 1 ? "s" : "");
            } else if (days < 30) {
                long weeks = days / 7;
                return "il y a " + weeks + " semaine" + (weeks > 1 ? "s" : "");
            } else {
                long months = days / 30;
                return "il y a " + months + " mois";
            }
        } catch (Exception e) {
            return "Récemment";
        }
    }
    
    /**
     * Charge les documents personnels
     */
    private void chargerDocuments() {
        documents = new ArrayList<>();
        try {
            if (membre != null) {
                // Créer des documents basés sur les cotisations et événements
                List<CotisationResponse> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 20);
                if (cotisations != null) {
                    for (CotisationResponse cot : cotisations) {
                        if ("PAYEE".equals(cot.getStatut()) && cot.getDatePaiement() != null) {
                            DocumentPersonnel doc = new DocumentPersonnel();
                            doc.setId(cot.getId());
                            doc.setNom("Reçu de cotisation - " + (cot.getNumeroReference() != null ? cot.getNumeroReference() : "N/A"));
                            doc.setType("PDF");
                            doc.setDateCreation(cot.getDatePaiement().toLocalDate());
                            doc.setTaille(245000); // 245 KB
                            documents.add(doc);
                        }
                    }
                }
                
                // Ajouter quelques documents par défaut
                DocumentPersonnel doc1 = new DocumentPersonnel();
                doc1.setId(UUID.randomUUID());
                doc1.setNom("Certificat d'adhésion.pdf");
                doc1.setType("PDF");
                doc1.setDateCreation(LocalDate.now().minusMonths(6));
                doc1.setTaille(512000);
                documents.add(doc1);
                
                DocumentPersonnel doc2 = new DocumentPersonnel();
                doc2.setId(UUID.randomUUID());
                doc2.setNom("Règlement intérieur.pdf");
                doc2.setType("PDF");
                doc2.setDateCreation(LocalDate.now().minusMonths(3));
                doc2.setTaille(1024000);
                documents.add(doc2);
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du chargement des documents");
        }
    }
    
    /**
     * Charge les notifications personnelles
     */
    private void chargerNotifications() {
        notifications = new ArrayList<>();
        try {
            if (membre != null) {
                // Créer des notifications basées sur les événements à venir
                var evenementsResponse = evenementService.listerAVenir(0, 5);
                if (evenementsResponse != null && evenementsResponse.getData() != null) {
                    for (EvenementResponse evt : evenementsResponse.getData()) {
                        NotificationPersonnelle notif = new NotificationPersonnelle();
                        notif.setId(UUID.randomUUID());
                        notif.setTitre("Nouvel événement");
                        notif.setMessage("Un nouvel événement a été programmé: " +
                                        (evt.getTitre() != null ? evt.getTitre() : ""));
                        if (evt.getDateCreation() != null) {
                            try {
                                notif.setDateCreation(evt.getDateCreation().toLocalDate());
                            } catch (Exception e) {
                                notif.setDateCreation(LocalDate.now().minusDays(1));
                            }
                        } else {
                            notif.setDateCreation(LocalDate.now().minusDays(1));
                        }
                        notif.setLue(false);
                        notifications.add(notif);
                    }
                }
                
                // Ajouter des notifications par défaut
                NotificationPersonnelle notif1 = new NotificationPersonnelle();
                notif1.setId(UUID.randomUUID());
                notif1.setTitre("Bienvenue");
                notif1.setMessage("Bienvenue dans votre espace personnel UnionFlow");
                notif1.setDateCreation(LocalDate.now().minusDays(7));
                notif1.setLue(true);
                notifications.add(0, notif1);
            }
        } catch (Exception e) {
            LOG.warnf(e, "Erreur lors du chargement des notifications");
        }
    }
    
    /**
     * Met à jour le profil
     */
    public void mettreAJourProfil() {
        try {
            if (membre != null) {
                membre = retryService.executeWithRetrySupplier(
                    () -> membreService.modifier(membre.getId(), membre),
                    "mise à jour du profil personnel"
                );
                errorHandler.showSuccess("Succès", "Votre profil a été mis à jour avec succès.");
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la mise à jour du profil");
            errorHandler.handleException(e, "lors de la mise à jour du profil personnel", null);
        }
    }
    
    /**
     * Actualise les données
     */
    public void actualiser() {
        chargerProfil();
        chargerStatistiques();
        chargerActivitesRecentes();
        errorHandler.showSuccess("Succès", "Données actualisées.");
    }
    
    private void initialiserStatistiquesVides() {
        statistiques.setActionsRealisees(0);
        statistiques.setEvenementsParticipes(0);
        statistiques.setTauxParticipation(0.0);
        statistiques.setEvaluationMoyenne(0.0);
    }
    
    // Getters et Setters
    public MembreResponse getMembre() { return membre; }
    public void setMembre(MembreResponse membre) { this.membre = membre; }
    
    public StatistiquesProfil getStatistiques() { return statistiques; }
    public void setStatistiques(StatistiquesProfil statistiques) { this.statistiques = statistiques; }
    
    public List<ActiviteRecente> getActivitesRecentes() { return activitesRecentes; }
    public void setActivitesRecentes(List<ActiviteRecente> activitesRecentes) { this.activitesRecentes = activitesRecentes; }
    
    public List<DocumentPersonnel> getDocuments() { return documents; }
    public void setDocuments(List<DocumentPersonnel> documents) { this.documents = documents; }
    
    public List<NotificationPersonnelle> getNotifications() { return notifications; }
    public void setNotifications(List<NotificationPersonnelle> notifications) { this.notifications = notifications; }
    
    // Classes internes
    public static class StatistiquesProfil implements Serializable {
        private int actionsRealisees;
        private int evenementsParticipes;
        private double tauxParticipation;
        private double evaluationMoyenne;
        
        public int getActionsRealisees() { return actionsRealisees; }
        public void setActionsRealisees(int actionsRealisees) { this.actionsRealisees = actionsRealisees; }
        
        public int getEvenementsParticipes() { return evenementsParticipes; }
        public void setEvenementsParticipes(int evenementsParticipes) { this.evenementsParticipes = evenementsParticipes; }
        
        public double getTauxParticipation() { return tauxParticipation; }
        public void setTauxParticipation(double tauxParticipation) { this.tauxParticipation = tauxParticipation; }
        
        public double getEvaluationMoyenne() { return evaluationMoyenne; }
        public void setEvaluationMoyenne(double evaluationMoyenne) { this.evaluationMoyenne = evaluationMoyenne; }
    }
    
    public static class ActiviteRecente implements Serializable {
        private String titre;
        private String description;
        private String dateHeure;
        private String icon;
        private String couleur;
        
        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 getDateHeure() { return dateHeure; }
        public void setDateHeure(String dateHeure) { this.dateHeure = dateHeure; }
        
        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 static class DocumentPersonnel implements Serializable {
        private UUID id;
        private String nom;
        private String type;
        private LocalDate dateCreation;
        private long taille;
        
        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; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public LocalDate getDateCreation() { return dateCreation; }
        public void setDateCreation(LocalDate dateCreation) { this.dateCreation = dateCreation; }
        
        public long getTaille() { return taille; }
        public void setTaille(long taille) { this.taille = taille; }
    }
    
    public static class NotificationPersonnelle implements Serializable {
        private UUID id;
        private String titre;
        private String message;
        private LocalDate dateCreation;
        private boolean lue;
        
        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 getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        
        public LocalDate getDateCreation() { return dateCreation; }
        public void setDateCreation(LocalDate dateCreation) { this.dateCreation = dateCreation; }
        
        public boolean isLue() { return lue; }
        public void setLue(boolean lue) { this.lue = lue; }
    }
}

