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.CotisationService;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.EvenementService;
import dev.lions.unionflow.client.service.NotificationService;
import dev.lions.unionflow.client.service.RetryService;
import java.util.Map;
import jakarta.faces.view.ViewScoped;
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 org.primefaces.event.FileUploadEvent;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Named("membreProfilBean")
@ViewScoped
public class MembreProfilBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(MembreProfilBean.class);
    
    // Constantes de navigation outcomes (WOU/DRY - réutilisables)
    private static final String OUTCOME_MEMBRE_LISTE = "membreListPage";
    private static final String OUTCOME_MEMBRE_COTISATIONS = "membreCotisationsPage";
    
    @Inject
    @RestClient
    private MembreService membreService;
    
    @Inject
    @RestClient
    private CotisationService cotisationService;
    
    @Inject
    @RestClient
    private EvenementService evenementService;
    
    @Inject
    @RestClient
    private NotificationService notificationService;
    
    @Inject
    ErrorHandlerService errorHandler;
    
    @Inject
    RetryService retryService;

    @Inject
    UserSession userSession;

    private Membre membre;
    private Membre membreEdit;
    private Statistiques statistiques;
    private CotisationsData cotisations;
    private EvenementsData evenements;
    private AidesData aides;
    private DemandesData demandes;
    private HistoriqueData historique;
    private ContactData contact;
    private UUID membreId;

    // ── Cycle de vie de l'adhésion ─────────────────────────────────────────
    /** UUID du lien MembreOrganisation (chargé en lazy depuis le backend) */
    private UUID membreOrgId;
    /** Statut d'adhésion dans l'organisation active (INVITE, EN_ATTENTE_VALIDATION, ACTIF, SUSPENDU…) */
    private String statutAdhesion;
    /** Motif saisi dans les dialogs de suspension / radiation */
    private String motifAction;
    /** Rôle à proposer lors d'une invitation */
    private String roleOrgInvit;

    @PostConstruct
    public void init() {
        // Récupérer membreId depuis les paramètres de requête (DRY/WOU - réutilisable)
        String idParam = jakarta.faces.context.FacesContext.getCurrentInstance()
            .getExternalContext().getRequestParameterMap().get("id");
        if (idParam != null && !idParam.isEmpty()) {
            try {
                membreId = UUID.fromString(idParam);
            } catch (IllegalArgumentException e) {
                LOG.errorf(e, "ID membre invalide: %s", idParam);
                errorHandler.showWarning("Erreur", "ID membre invalide");
                return;
            }
        }
        
        if (membreId == null) {
            LOG.warn("Aucun membreId fourni, impossible de charger le profil");
            errorHandler.showWarning("Attention", "Aucun membre sélectionné");
            return;
        }
        
        chargerMembre();
        chargerStatistiques();
        chargerCotisations();
        chargerEvenements();
        chargerAides();
        chargerDemandes();
        chargerHistorique();
        initContact();
    }
    
    private void chargerMembre() {
        try {
            MembreResponse dto = retryService.executeWithRetrySupplier(
                () -> membreService.obtenirParId(membreId),
                "chargement d'un membre pour profil"
            );
            membre = convertToMembre(dto);
            
            // Copie pour l'édition
            membreEdit = new Membre();
            copierMembre(membre, membreEdit);
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement du membre");
            errorHandler.handleException(e, "lors du chargement du membre", null);
            membre = new Membre();
            membre.setId(membreId);
        }
    }
    
    private Membre convertToMembre(MembreResponse dto) {
        Membre membre = new Membre();
        membre.setId(dto.getId());
        membre.setNumeroMembre(dto.getNumeroMembre());
        membre.setPrenom(dto.getPrenom());
        membre.setNom(dto.getNom());
        membre.setEmail(dto.getEmail());
        membre.setTelephone(dto.getTelephone());
        membre.setDateNaissance(dto.getDateNaissance());
        membre.setProfession(dto.getProfession());
        membre.setAdresse(dto.getAdresse());
        membre.setVille(dto.getVille());
        membre.setStatut(dto.getStatutCompte() != null ? dto.getStatutCompte() : "ACTIF");
        membre.setDateAdhesion(dto.getDateAdhesion());
        membre.setEntite(dto.getOrganisationNom());
        membre.setPhotoUrl(dto.getPhotoUrl());
        membre.setStatutMatrimonial(dto.getStatutMatrimonial());
        membre.setNationalite(dto.getNationalite());
        // typeMembre calculé depuis les rôles (cohérent avec MembreSummaryResponse.typeMembre())
        membre.setTypeMembre(calculerTypeMembre(dto.getRoles()));
        return membre;
    }

    private String calculerTypeMembre(List<String> roles) {
        if (roles == null || roles.isEmpty()) return "ACTIF";
        if (roles.contains("PRESIDENT"))          return "PRESIDENT";
        if (roles.contains("VICE_PRESIDENT"))     return "VICE_PRESIDENT";
        if (roles.contains("SECRETAIRE"))         return "SECRETAIRE";
        if (roles.contains("TRESORIER"))          return "TRESORIER";
        if (roles.contains("ADMIN_ORGANISATION")) return "ADMIN";
        if (roles.contains("MODERATEUR"))         return "MODERATEUR";
        return "ACTIF";
    }
    
    private void chargerStatistiques() {
        statistiques = new Statistiques();
        try {
            // Cotisations payées pour ce membre
            List<dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse> cotisationsList =
                    cotisationService.obtenirParMembre(membreId, 0, 100);
            long cotisationsPayees = cotisationsList != null
                    ? cotisationsList.stream().filter(c -> "PAYEE".equals(c.getStatut()) || "VALIDE".equals(c.getStatut())).count()
                    : 0L;
            statistiques.setCotisationsPayees((int) cotisationsPayees);

            // Événements depuis MembreResponse (champ déjà chargé)
            if (membre != null) {
                statistiques.setEvenementsTotal(0); // pas d'API par membre
            }
        } catch (Exception e) {
            LOG.warnf("Impossible de charger les statistiques détaillées: %s", e.getMessage());
        }
    }
    
    private void chargerCotisations() {
        cotisations = new CotisationsData();
        try {
            List<dev.lions.unionflow.server.api.dto.cotisation.response.CotisationResponse> liste =
                    retryService.executeWithRetrySupplier(
                            () -> cotisationService.obtenirParMembre(membreId, 0, 12),
                            "chargement des cotisations du membre");

            List<PaiementCotisation> historiqueCot = new ArrayList<>();
            if (liste != null) {
                // Trouver la dernière cotisation payée pour le statut global
                liste.stream()
                        .filter(c -> "PAYEE".equals(c.getStatut()) || "VALIDE".equals(c.getStatut()))
                        .findFirst()
                        .ifPresent(derniere -> {
                            cotisations.setStatutActuel("À jour");
                            cotisations.setStatutSeverity("success");
                            cotisations.setDernierPaiement(
                                    derniere.getDatePaiementFormattee() != null
                                            ? derniere.getDatePaiementFormattee()
                                            : (derniere.getPeriode() != null ? derniere.getPeriode() : "—"));
                        });

                // Prochaine échéance : la plus proche non payée
                liste.stream()
                        .filter(c -> !"PAYEE".equals(c.getStatut()) && !"VALIDE".equals(c.getStatut()))
                        .findFirst()
                        .ifPresent(prochaine -> {
                            cotisations.setStatutActuel("En attente");
                            cotisations.setStatutSeverity("warning");
                            cotisations.setProchaineEcheance(
                                    prochaine.getDateEcheanceFormattee() != null
                                            ? prochaine.getDateEcheanceFormattee() : "—");
                            cotisations.setProchaineEcheanceClass(
                                    "EN_RETARD".equals(prochaine.getStatut()) ? "text-red-500" : "text-orange-500");
                        });

                // Historique
                for (var c : liste) {
                    PaiementCotisation p = new PaiementCotisation();
                    p.setDate(c.getDateEcheance());
                    p.setMontant(c.getMontant() != null ? c.getMontant().doubleValue() : 0.0);
                    p.setModePaiement(c.getModePaiementLibelle() != null ? c.getModePaiementLibelle() : "—");
                    p.setModeIcon(c.getModePaiementIcon() != null ? c.getModePaiementIcon() : "pi-money-bill");
                    p.setStatut(c.getStatutLibelle() != null ? c.getStatutLibelle() : c.getStatut());
                    p.setStatutSeverity(c.getStatutSeverity() != null ? c.getStatutSeverity() : "secondary");
                    historiqueCot.add(p);
                }
            }
            if (cotisations.getStatutActuel() == null) {
                cotisations.setStatutActuel("Aucune cotisation");
                cotisations.setStatutSeverity("secondary");
            }
            cotisations.setHistorique(historiqueCot);
        } catch (Exception e) {
            LOG.warnf("Impossible de charger les cotisations: %s", e.getMessage());
            cotisations.setStatutActuel("Indisponible");
            cotisations.setStatutSeverity("secondary");
            cotisations.setHistorique(new ArrayList<>());
        }
    }
    
    private void chargerEvenements() {
        // Pas d'endpoint /api/evenements/membre/{id} — liste vide pour l'instant
        evenements = new EvenementsData();
        evenements.setRecents(new ArrayList<>());
    }

    private void chargerAides() {
        // Pas d'endpoint /api/demandes-aide?demandeurId — liste vide pour l'instant
        aides = new AidesData();
        aides.setRecues(new ArrayList<>());
    }

    private void chargerDemandes() {
        // Pas d'endpoint /api/demandes-aide?demandeurId — liste vide pour l'instant
        demandes = new DemandesData();
        demandes.setEnCours(new ArrayList<>());
    }

    private void chargerHistorique() {
        // Pas d'endpoint d'historique par membre — liste vide pour l'instant
        historique = new HistoriqueData();
        historique.setActivites(new ArrayList<>());
    }
    
    private void initContact() {
        contact = new ContactData();
        contact.setCanaux(new ArrayList<>());
    }
    
    // Actions
    public void changerPhoto(FileUploadEvent event) {
        // Logique de changement de photo
        LOG.infof("Photo changée: %s", event.getFile().getFileName());
    }
    
    public String gererCotisations() {
        // Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
        return OUTCOME_MEMBRE_COTISATIONS + "?id=" + membre.getId() + "&faces-redirect=true";
    }
    
    public void sauvegarderModifications() {
        try {
            // Convertir Membre vers MembreResponse pour l'envoi au backend (DRY/WOU)
            MembreResponse dto = convertirMembreVersDTO(membreEdit);
            retryService.executeWithRetrySupplier(
                () -> {
                    membreService.modifier(membreId, dto);
                    return null;
                },
                "mise à jour du profil d'un membre"
            );
            
            // Mettre à jour le membre local
            copierMembre(membreEdit, membre);
            
            LOG.infof("Profil mis à jour pour: %s", membre.getNomComplet());
            errorHandler.showSuccess("Succès", "Le 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", null);
        }
    }
    
    public void envoyerMessage() {
        if (contact == null || contact.getMessage() == null || contact.getMessage().trim().isEmpty()) {
            errorHandler.showWarning("Attention", "Veuillez saisir un message");
            return;
        }
        
        try {
            String sujet = contact.getSujet() != null && !contact.getSujet().trim().isEmpty() 
                ? contact.getSujet() 
                : "Message depuis UnionFlow";
            
            // Envoyer la notification via le service (DRY/WOU - réutilise NotificationService)
            List<UUID> membreIds = List.of(membreId);
            List<String> canaux = contact.getCanaux() != null && !contact.getCanaux().isEmpty()
                ? contact.getCanaux()
                : List.of("IN_APP", "EMAIL");
            
            NotificationService.NotificationGroupeeRequest request = 
                new NotificationService.NotificationGroupeeRequest(membreIds, sujet, contact.getMessage(), canaux);
            
            retryService.executeWithRetrySupplier(
                () -> {
                    notificationService.envoyerNotificationsGroupees(request);
                    return null;
                },
                "envoi d'un message à un membre"
            );
            
            LOG.infof("Message envoyé: %s via %s", sujet, canaux);
            errorHandler.showSuccess("Succès", "Message envoyé avec succès");
            
            // Réinitialiser le formulaire
            contact = new ContactData();
            contact.setCanaux(new ArrayList<>());
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de l'envoi du message");
            errorHandler.handleException(e, "lors de l'envoi d'un message", null);
        }
    }
    
    public void envoyerRappelCotisation() {
        try {
            // Envoyer rappel via le service de cotisations (DRY/WOU)
            List<UUID> membreIds = List.of(membreId);
            retryService.executeWithRetrySupplier(
                () -> {
                    cotisationService.envoyerRappelsGroupes(membreIds);
                    return null;
                },
                "envoi d'un rappel de cotisation"
            );
            
            LOG.infof("Rappel de cotisation envoyé à: %s", membre.getEmail());
            errorHandler.showSuccess("Succès", "Rappel de cotisation envoyé");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de l'envoi du rappel");
            errorHandler.handleException(e, "lors de l'envoi d'un rappel de cotisation", null);
        }
    }
    
    public void suspendre() {
        try {
            retryService.executeWithRetrySupplier(
                () -> {
                    membreService.suspendre(membreId);
                    return null;
                },
                "suspension d'un membre"
            );
            membre.setStatut("SUSPENDU");
            LOG.infof("Membre suspendu: %s", membre.getNomComplet());
            errorHandler.showSuccess("Succès", "Le membre a été suspendu");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la suspension");
            errorHandler.handleException(e, "lors de la suspension d'un membre", null);
        }
    }
    
    public void reactiver() {
        try {
            retryService.executeWithRetrySupplier(
                () -> {
                    membreService.activer(membreId);
                    return null;
                },
                "réactivation d'un membre"
            );
            membre.setStatut("ACTIF");
            LOG.infof("Membre réactivé: %s", membre.getNomComplet());
            errorHandler.showSuccess("Succès", "Le membre a été réactivé");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la réactivation");
            errorHandler.handleException(e, "lors de la réactivation d'un membre", null);
        }
    }
    
    // ── Cycle de vie de l'adhésion ─────────────────────────────────────────

    /** Charge le statut d'adhésion du membre dans l'organisation active. */
    public void chargerStatutAdhesion() {
        UUID activeOrgId = userSession.getActiveOrganisationId();
        if (membreId == null || activeOrgId == null) return;
        try {
            Map<String, Object> info = retryService.executeWithRetrySupplier(
                () -> membreService.getAdhesionStatut(membreId, activeOrgId),
                "chargement statut adhésion"
            );
            statutAdhesion = info != null ? String.valueOf(info.get("statut")) : null;
            Object oid = info != null ? info.get("membreOrgId") : null;
            if (oid != null) membreOrgId = UUID.fromString(oid.toString());
        } catch (Exception e) {
            statutAdhesion = null;
            LOG.debugf("Aucune adhésion trouvée pour membre %s dans l'org active", membreId);
        }
    }

    /** Invite le membre dans l'organisation active (crée un lien INVITE). */
    public void inviterDansOrgActive() {
        UUID activeOrgId = userSession.getActiveOrganisationId();
        if (membreId == null || activeOrgId == null) {
            errorHandler.showWarning("Attention", "Organisation active non définie");
            return;
        }
        try {
            retryService.executeWithRetrySupplier(
                () -> membreService.inviterMembreOrg(membreId, activeOrgId, roleOrgInvit),
                "invitation d'un membre"
            );
            statutAdhesion = "INVITE";
            errorHandler.showSuccess("Succès", "Invitation envoyée au membre");
        } catch (Exception e) {
            errorHandler.handleException(e, "lors de l'invitation du membre", null);
        }
    }

    /** Active l'adhésion du membre dans l'organisation active. */
    public void activerAdhesion() {
        UUID activeOrgId = userSession.getActiveOrganisationId();
        if (membreId == null || activeOrgId == null) return;
        try {
            retryService.executeWithRetrySupplier(
                () -> membreService.activerAdhesion(membreId, activeOrgId, Map.of("motif", motifAction != null ? motifAction : "")),
                "activation adhésion"
            );
            statutAdhesion = "ACTIF";
            motifAction = null;
            errorHandler.showSuccess("Succès", "Adhésion activée");
        } catch (Exception e) {
            errorHandler.handleException(e, "lors de l'activation de l'adhésion", null);
        }
    }

    /** Suspend l'adhésion du membre dans l'organisation active. */
    public void suspendrAdhesion() {
        UUID activeOrgId = userSession.getActiveOrganisationId();
        if (membreId == null || activeOrgId == null) return;
        try {
            retryService.executeWithRetrySupplier(
                () -> membreService.suspendrAdhesion(membreId, activeOrgId, Map.of("motif", motifAction != null ? motifAction : "")),
                "suspension adhésion"
            );
            statutAdhesion = "SUSPENDU";
            motifAction = null;
            errorHandler.showSuccess("Succès", "Adhésion suspendue");
        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la suspension de l'adhésion", null);
        }
    }

    /** Radie le membre de l'organisation active. */
    public void radierAdhesion() {
        UUID activeOrgId = userSession.getActiveOrganisationId();
        if (membreId == null || activeOrgId == null) return;
        try {
            retryService.executeWithRetrySupplier(
                () -> membreService.radierAdhesion(membreId, activeOrgId, Map.of("motif", motifAction != null ? motifAction : "")),
                "radiation adhésion"
            );
            statutAdhesion = "RADIE";
            motifAction = null;
            errorHandler.showSuccess("Succès", "Le membre a été radié de l'organisation");
        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la radiation du membre", null);
        }
    }

    // Getters/setters cycle de vie
    public String getStatutAdhesion() { return statutAdhesion; }
    public String getMotifAction() { return motifAction; }
    public void setMotifAction(String motifAction) { this.motifAction = motifAction; }
    public String getRoleOrgInvit() { return roleOrgInvit; }
    public void setRoleOrgInvit(String roleOrgInvit) { this.roleOrgInvit = roleOrgInvit; }

    public void exporterDonnees() {
        try {
            // Exporter les données du membre via le service (DRY/WOU)
            byte[] excelData = retryService.executeWithRetrySupplier(
                () -> membreService.exporterSelection(List.of(membreId), "EXCEL"),
                "export des données d'un membre"
            );
            
            // Téléchargement du fichier Excel via JSF
            jakarta.faces.context.FacesContext facesContext = jakarta.faces.context.FacesContext.getCurrentInstance();
            jakarta.servlet.http.HttpServletResponse response = 
                (jakarta.servlet.http.HttpServletResponse) facesContext.getExternalContext().getResponse();
            
            response.reset();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", 
                "attachment; filename=\"membre_" + membre.getNumeroMembre() + "_" + LocalDate.now() + ".xlsx\"");
            response.setContentLength(excelData.length);
            
            response.getOutputStream().write(excelData);
            response.getOutputStream().flush();
            facesContext.responseComplete();
            
            LOG.infof("Export des données pour: %s", membre.getNomComplet());
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de l'export");
            errorHandler.handleException(e, "lors de l'export des données d'un membre", null);
        }
    }
    
    public String supprimer() {
        try {
            retryService.executeWithRetrySupplier(
                () -> {
                    membreService.supprimer(membreId);
                    return null;
                },
                "suppression d'un membre"
            );
            LOG.infof("Membre supprimé: %s", membre.getNomComplet());
            errorHandler.showSuccess("Succès", "Le membre a été supprimé");
            return OUTCOME_MEMBRE_LISTE + "?faces-redirect=true";
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la suppression");
            errorHandler.handleException(e, "lors de la suppression d'un membre", null);
            return null;
        }
    }
    
    /**
     * Convertit un Membre (classe interne) vers MembreResponse pour l'envoi au backend (DRY/WOU)
     */
    private MembreResponse convertirMembreVersDTO(Membre membre) {
        MembreResponse dto = new MembreResponse();
        dto.setId(membre.getId());
        dto.setNumeroMembre(membre.getNumeroMembre());
        dto.setPrenom(membre.getPrenom());
        dto.setNom(membre.getNom());
        dto.setEmail(membre.getEmail());
        dto.setTelephone(membre.getTelephone());
        dto.setDateNaissance(membre.getDateNaissance());
        dto.setProfession(membre.getProfession());
        // Note: MembreResponse n'a pas de setAdresse() ni setStatut()
        dto.setStatutCompte(membre.getStatut()); // Corrigé: setStatutCompte
        // Note: dateInscription sera géré par le backend si nécessaire
        return dto;
    }
    
    private void copierMembre(Membre source, Membre destination) {
        destination.setId(source.getId());
        destination.setPrenom(source.getPrenom());
        destination.setNom(source.getNom());
        destination.setEmail(source.getEmail());
        destination.setTelephone(source.getTelephone());
        destination.setDateNaissance(source.getDateNaissance());
        destination.setProfession(source.getProfession());
        destination.setAdresse(source.getAdresse());
    }
    
    // Getters et Setters
    public Membre getMembre() { return membre; }
    public void setMembre(Membre membre) { this.membre = membre; }
    
    public Membre getMembreEdit() { return membreEdit; }
    public void setMembreEdit(Membre membreEdit) { this.membreEdit = membreEdit; }
    
    public Statistiques getStatistiques() { return statistiques; }
    public void setStatistiques(Statistiques statistiques) { this.statistiques = statistiques; }
    
    public CotisationsData getCotisations() { return cotisations; }
    public void setCotisations(CotisationsData cotisations) { this.cotisations = cotisations; }
    
    public EvenementsData getEvenements() { return evenements; }
    public void setEvenements(EvenementsData evenements) { this.evenements = evenements; }
    
    public AidesData getAides() { return aides; }
    public void setAides(AidesData aides) { this.aides = aides; }
    
    public DemandesData getDemandes() { return demandes; }
    public void setDemandes(DemandesData demandes) { this.demandes = demandes; }
    
    public HistoriqueData getHistorique() { return historique; }
    public void setHistorique(HistoriqueData historique) { this.historique = historique; }
    
    public ContactData getContact() { return contact; }
    public void setContact(ContactData contact) { this.contact = contact; }
    
    public UUID getMembreId() { return membreId; }
    public void setMembreId(UUID membreId) { this.membreId = membreId; }
    
    // Classes internes
    public static class Membre {
        private UUID id;
        private String numeroMembre;
        private String prenom;
        private String nom;
        private String email;
        private String telephone;
        private LocalDate dateNaissance;
        private String genre;
        private String situationFamiliale;
        private String statutMatrimonial;
        private String nationalite;
        private String profession;
        private String adresse;
        private String ville;
        private String pays;
        private String typeMembre;
        private String statut;
        private String entite;
        private LocalDate dateAdhesion;
        private String cotisationStatut;
        private int tauxParticipation;
        private String photoUrl;
        private List<MembreFamille> famille = new ArrayList<>();
        
        // Getters et setters
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getNumeroMembre() { return numeroMembre; }
        public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
        
        public String getPrenom() { return prenom; }
        public void setPrenom(String prenom) { this.prenom = prenom; }
        
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        
        public String getTelephone() { return telephone; }
        public void setTelephone(String telephone) { this.telephone = telephone; }
        
        public LocalDate getDateNaissance() { return dateNaissance; }
        public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
        
        public String getGenre() { return genre; }
        public void setGenre(String genre) { this.genre = genre; }
        
        public String getSituationFamiliale() { return situationFamiliale; }
        public void setSituationFamiliale(String situationFamiliale) { this.situationFamiliale = situationFamiliale; }

        public String getStatutMatrimonial() { return statutMatrimonial; }
        public void setStatutMatrimonial(String statutMatrimonial) { this.statutMatrimonial = statutMatrimonial; }

        public String getNationalite() { return nationalite; }
        public void setNationalite(String nationalite) { this.nationalite = nationalite; }

        public String getProfession() { return profession; }
        public void setProfession(String profession) { this.profession = profession; }
        
        public String getAdresse() { return adresse; }
        public void setAdresse(String adresse) { this.adresse = adresse; }
        
        public String getVille() { return ville; }
        public void setVille(String ville) { this.ville = ville; }
        
        public String getPays() { return pays; }
        public void setPays(String pays) { this.pays = pays; }
        
        public String getTypeMembre() { return typeMembre; }
        public void setTypeMembre(String typeMembre) { this.typeMembre = typeMembre; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getEntite() { return entite; }
        public void setEntite(String entite) { this.entite = entite; }
        
        public LocalDate getDateAdhesion() { return dateAdhesion; }
        public void setDateAdhesion(LocalDate dateAdhesion) { this.dateAdhesion = dateAdhesion; }
        
        public String getCotisationStatut() { return cotisationStatut; }
        public void setCotisationStatut(String cotisationStatut) { this.cotisationStatut = cotisationStatut; }
        
        public int getTauxParticipation() { return tauxParticipation; }
        public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
        
        public String getPhotoUrl() { return photoUrl; }
        public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; }
        
        public List<MembreFamille> getFamille() { return famille; }
        public void setFamille(List<MembreFamille> famille) { this.famille = famille; }
        
        // Propriétés dérivées
        public String getNomComplet() {
            return prenom + " " + nom;
        }
        
        public String getInitiales() {
            return (prenom != null ? prenom.substring(0, 1) : "") + 
                   (nom != null ? nom.substring(0, 1) : "");
        }
        
        public String getStatutSeverity() {
            if (statut == null) return "secondary";
            return switch (statut) {
                case "ACTIF" -> "success";
                case "INACTIF" -> "warning";
                case "SUSPENDU" -> "danger";
                case "RADIE" -> "danger";
                default -> "secondary";
            };
        }

        public String getStatutIcon() {
            if (statut == null) return "pi-circle";
            return switch (statut) {
                case "ACTIF" -> "pi-check";
                case "INACTIF" -> "pi-pause";
                case "SUSPENDU" -> "pi-ban";
                case "RADIE" -> "pi-times";
                default -> "pi-circle";
            };
        }

        public String getTypeSeverity() {
            if (typeMembre == null) return "info";
            return switch (typeMembre) {
                case "ACTIF" -> "info";
                case "ASSOCIE" -> "success";
                case "BIENFAITEUR" -> "warning";
                case "HONORAIRE" -> "secondary";
                default -> "info";
            };
        }

        public String getTypeIcon() {
            if (typeMembre == null) return "pi-user";
            return switch (typeMembre) {
                case "ACTIF" -> "pi-user";
                case "ASSOCIE" -> "pi-users";
                case "BIENFAITEUR" -> "pi-star";
                case "HONORAIRE" -> "pi-crown";
                default -> "pi-user";
            };
        }
        
        public String getAnciennete() {
            if (dateAdhesion == null) return "N/A";
            long mois = java.time.temporal.ChronoUnit.MONTHS.between(dateAdhesion, LocalDate.now());
            if (mois < 12) return mois + " mois";
            return (mois / 12) + " an" + (mois / 12 > 1 ? "s" : "");
        }
        
        public String getCotisationColor() {
            return cotisationStatut != null && cotisationStatut.equals("À jour") ? "text-green-500" : "text-red-500";
        }
    }
    
    public static class MembreFamille {
        private String nomComplet;
        private String relation;
        private LocalDate dateNaissance;
        private boolean beneficiaire;
        
        // Getters et setters
        public String getNomComplet() { return nomComplet; }
        public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
        
        public String getRelation() { return relation; }
        public void setRelation(String relation) { this.relation = relation; }
        
        public LocalDate getDateNaissance() { return dateNaissance; }
        public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
        
        public boolean isBeneficiaire() { return beneficiaire; }
        public void setBeneficiaire(boolean beneficiaire) { this.beneficiaire = beneficiaire; }
    }
    
    public static class Statistiques {
        private int evenementsParticipes;
        private int cotisationsPayees;
        private int aidesRecues;
        private int scoreEngagement;
        private int tauxParticipation;
        private int evenementsAnnee;
        private int evenementsTotal;
        private int evenementsOrganises;
        private int absences;
        
        // Getters et setters
        public int getEvenementsParticipes() { return evenementsParticipes; }
        public void setEvenementsParticipes(int evenementsParticipes) { this.evenementsParticipes = evenementsParticipes; }
        
        public int getCotisationsPayees() { return cotisationsPayees; }
        public void setCotisationsPayees(int cotisationsPayees) { this.cotisationsPayees = cotisationsPayees; }
        
        public int getAidesRecues() { return aidesRecues; }
        public void setAidesRecues(int aidesRecues) { this.aidesRecues = aidesRecues; }
        
        public int getScoreEngagement() { return scoreEngagement; }
        public void setScoreEngagement(int scoreEngagement) { this.scoreEngagement = scoreEngagement; }
        
        public int getTauxParticipation() { return tauxParticipation; }
        public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
        
        public int getEvenementsAnnee() { return evenementsAnnee; }
        public void setEvenementsAnnee(int evenementsAnnee) { this.evenementsAnnee = evenementsAnnee; }
        
        public int getEvenementsTotal() { return evenementsTotal; }
        public void setEvenementsTotal(int evenementsTotal) { this.evenementsTotal = evenementsTotal; }
        
        public int getEvenementsOrganises() { return evenementsOrganises; }
        public void setEvenementsOrganises(int evenementsOrganises) { this.evenementsOrganises = evenementsOrganises; }
        
        public int getAbsences() { return absences; }
        public void setAbsences(int absences) { this.absences = absences; }
    }
    
    public static class CotisationsData {
        private String statutActuel;
        private String statutSeverity;
        private String dernierPaiement;
        private String prochaineEcheance;
        private String prochaineEcheanceClass;
        private String totalAnnee;
        private List<PaiementCotisation> historique = new ArrayList<>();
        
        // Getters et setters
        public String getStatutActuel() { return statutActuel; }
        public void setStatutActuel(String statutActuel) { this.statutActuel = statutActuel; }
        
        public String getStatutSeverity() { return statutSeverity; }
        public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
        
        public String getDernierPaiement() { return dernierPaiement; }
        public void setDernierPaiement(String dernierPaiement) { this.dernierPaiement = dernierPaiement; }
        
        public String getProchaineEcheance() { return prochaineEcheance; }
        public void setProchaineEcheance(String prochaineEcheance) { this.prochaineEcheance = prochaineEcheance; }
        
        public String getProchaineEcheanceClass() { return prochaineEcheanceClass; }
        public void setProchaineEcheanceClass(String prochaineEcheanceClass) { this.prochaineEcheanceClass = prochaineEcheanceClass; }
        
        public String getTotalAnnee() { return totalAnnee; }
        public void setTotalAnnee(String totalAnnee) { this.totalAnnee = totalAnnee; }
        
        public List<PaiementCotisation> getHistorique() { return historique; }
        public void setHistorique(List<PaiementCotisation> historique) { this.historique = historique; }
    }
    
    public static class PaiementCotisation {
        private LocalDate date;
        private Double montant;
        private String modePaiement;
        private String modeIcon;
        private String statut;
        private String statutSeverity;
        
        // Getters et setters
        public LocalDate getDate() { return date; }
        public void setDate(LocalDate date) { this.date = date; }
        
        public Double getMontant() { return montant; }
        public void setMontant(Double montant) { this.montant = montant; }
        
        public String getModePaiement() { return modePaiement; }
        public void setModePaiement(String modePaiement) { this.modePaiement = modePaiement; }
        
        public String getModeIcon() { return modeIcon; }
        public void setModeIcon(String modeIcon) { this.modeIcon = modeIcon; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getStatutSeverity() { return statutSeverity; }
        public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
    }
    
    public static class EvenementsData {
        private List<EvenementParticipation> recents = new ArrayList<>();
        
        public List<EvenementParticipation> getRecents() { return recents; }
        public void setRecents(List<EvenementParticipation> recents) { this.recents = recents; }
    }
    
    public static class EvenementParticipation {
        private String titre;
        private String date;
        private String lieu;
        private String participation;
        private String participationSeverity;
        private String role;
        private String typeIcon;
        private String typeColorClass;
        
        // Getters et setters
        public String getTitre() { return titre; }
        public void setTitre(String titre) { this.titre = titre; }
        
        public String getDate() { return date; }
        public void setDate(String date) { this.date = date; }
        
        public String getLieu() { return lieu; }
        public void setLieu(String lieu) { this.lieu = lieu; }
        
        public String getParticipation() { return participation; }
        public void setParticipation(String participation) { this.participation = participation; }
        
        public String getParticipationSeverity() { return participationSeverity; }
        public void setParticipationSeverity(String participationSeverity) { this.participationSeverity = participationSeverity; }
        
        public String getRole() { return role; }
        public void setRole(String role) { this.role = role; }
        
        public String getTypeIcon() { return typeIcon; }
        public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
        
        public String getTypeColorClass() { return typeColorClass; }
        public void setTypeColorClass(String typeColorClass) { this.typeColorClass = typeColorClass; }
    }
    
    public static class AidesData {
        private List<Aide> recues = new ArrayList<>();
        
        public List<Aide> getRecues() { return recues; }
        public void setRecues(List<Aide> recues) { this.recues = recues; }
    }
    
    public static class Aide {
        private String type;
        private Double montant;
        private LocalDate date;
        private String statut;
        private String statutSeverity;
        private String typeIcon;
        private String typeColor;
        
        // Getters et setters
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public Double getMontant() { return montant; }
        public void setMontant(Double montant) { this.montant = montant; }
        
        public LocalDate getDate() { return date; }
        public void setDate(LocalDate date) { this.date = date; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getStatutSeverity() { return statutSeverity; }
        public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
        
        public String getTypeIcon() { return typeIcon; }
        public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
        
        public String getTypeColor() { return typeColor; }
        public void setTypeColor(String typeColor) { this.typeColor = typeColor; }
    }
    
    public static class DemandesData {
        private List<Demande> enCours = new ArrayList<>();
        
        public List<Demande> getEnCours() { return enCours; }
        public void setEnCours(List<Demande> enCours) { this.enCours = enCours; }
    }
    
    public static class Demande {
        private String type;
        private String objet;
        private LocalDate dateDepot;
        private String statut;
        private String statutSeverity;
        
        // Getters et setters
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getObjet() { return objet; }
        public void setObjet(String objet) { this.objet = objet; }
        
        public LocalDate getDateDepot() { return dateDepot; }
        public void setDateDepot(LocalDate dateDepot) { this.dateDepot = dateDepot; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getStatutSeverity() { return statutSeverity; }
        public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
    }
    
    public static class HistoriqueData {
        private List<Activite> activites = new ArrayList<>();
        
        public List<Activite> getActivites() { return activites; }
        public void setActivites(List<Activite> activites) { this.activites = activites; }
    }
    
    public static class Activite {
        private String description;
        private String date;
        private String auteur;
        private String icone;
        private String couleur;
        private String details;
        
        // Getters et setters
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getDate() { return date; }
        public void setDate(String date) { this.date = date; }
        
        public String getAuteur() { return auteur; }
        public void setAuteur(String auteur) { this.auteur = auteur; }
        
        public String getIcone() { return icone; }
        public void setIcone(String icone) { this.icone = icone; }
        
        public String getCouleur() { return couleur; }
        public void setCouleur(String couleur) { this.couleur = couleur; }
        
        public String getDetails() { return details; }
        public void setDetails(String details) { this.details = details; }
    }
    
    public static class ContactData {
        private String sujet;
        private String message;
        private List<String> canaux = new ArrayList<>();
        
        // Getters et setters
        public String getSujet() { return sujet; }
        public void setSujet(String sujet) { this.sujet = sujet; }
        
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        
        public List<String> getCanaux() { return canaux; }
        public void setCanaux(List<String> canaux) { this.canaux = canaux; }
    }
}
