package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.constants.StatutOrganisationConstants;
import dev.lions.unionflow.client.constants.ViewPaths;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationResponse;
import dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse;
import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.server.api.dto.reference.response.TypeReferenceResponse;
import dev.lions.unionflow.server.api.dto.common.PagedResponse;
import dev.lions.unionflow.client.service.OrganisationService;
import dev.lions.unionflow.client.service.CacheService;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import dev.lions.unionflow.client.service.TypeCatalogueService;
import dev.lions.unionflow.client.service.RestClientExceptionMapper;
import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;

import jakarta.faces.model.SelectItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Bean de gestion des organisations.
 * 
 * <p>
 * Intègre les meilleures pratiques de production :
 * <ul>
 * <li>ErrorHandlerService pour la gestion centralisée des erreurs</li>
 * <li>RetryService pour les retries automatiques</li>
 * <li>CacheService pour optimiser les performances</li>
 * <li>Logging structuré avec JBoss Logging</li>
 * <li>Validation robuste avec rollback</li>
 * </ul>
 * 
 * @author UnionFlow Team
 * @version 2.0
 * @since 2025-12-24
 */
@Named("organisationsBean")
@ViewScoped
public class OrganisationsBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(OrganisationsBean.class);

    // ========== INJECTIONS ==========

    @Inject
    @RestClient
    OrganisationService organisationService;

    @Inject
    ErrorHandlerService errorHandler;

    @Inject
    CacheService cacheService;

    @Inject
    RetryService retryService;

    @Inject
    TypeCatalogueService typeCatalogueService;

    // ========== DONNÉES ==========

    private List<OrganisationSummaryResponse> organisations = new ArrayList<>();
    private List<OrganisationSummaryResponse> organisationsFiltrees;

    private OrganisationResponse organisationSelectionnee;
    private OrganisationResponse nouvelleOrganisation;
    private OrganisationResponse backupOrganisation; // Pour rollback
    /** Organisation en attente de confirmation de suppression (flux explicite). */
    private OrganisationResponse organisationPourSuppression;
    /** Organisation en attente de confirmation de bascule de statut (flux explicite). */
    private OrganisationResponse organisationPourStatut;

    private long totalOrganisations;
    private long organisationsActives;
    private long organisationsInactives;

    // ========== FILTRES ==========

    private String rechercheGlobale;
    private String filtreStatut;
    private String filtreType;
    private String filtreRegion;

    // ========== INITIALISATION ==========

    @PostConstruct
    public void init() {
        LOG.info("Initialisation du bean OrganisationsBean");

        try {
            chargerOrganisations();
            chargerStatistiques();

            LOG.info("Initialisation terminée avec succès");

        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de l'initialisation");
            errorHandler.handleException(e, "lors de l'initialisation du bean",
                    "Impossible d'initialiser la page. Veuillez rafraîchir.");
        }
    }

    // ========== CHARGEMENT DES DONNÉES ==========

    /**
     * Charge les organisations depuis le backend avec retry automatique.
     */
    public void chargerOrganisations() {
        try {
            LOG.debug("Chargement des organisations");
            PagedResponse<OrganisationSummaryResponse> response = retryService.executeWithRetrySupplier(
                    () -> organisationService.listerToutes(0, 1000),
                    "chargement de toutes les organisations");
            organisations = (response != null && response.getData() != null) ? response.getData() : new ArrayList<OrganisationSummaryResponse>();
            // typeCatalogueService.enrichir(organisations); // DISABLED: enrichir expects OrganisationResponse, OrganisationSummaryResponse already has typeOrganisationLibelle
            organisationsFiltrees = new ArrayList<>(organisations);
            LOG.infof("Organisations chargées: %d", organisations.size());

        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des organisations");
            errorHandler.handleException(e, "lors du chargement des organisations", null);
            organisations = new ArrayList<>();
            organisationsFiltrees = new ArrayList<>();
        }
    }

    /**
     * Charge les statistiques (mises en cache).
     */
    private void chargerStatistiques() {
        try {
            List<OrganisationSummaryResponse> toutes = cacheService.getOrLoad(
                    "organisations-toutes",
                    () -> {
                        LOG.debug("Chargement de toutes les organisations pour les statistiques");
                        try {
                            PagedResponse<OrganisationSummaryResponse> response = retryService
                                    .executeWithRetrySupplier(
                                            () -> organisationService.listerToutes(0, 10000),
                                            "chargement des statistiques");
                            return (response != null && response.getData() != null) ? response.getData()
                                    : new ArrayList<OrganisationSummaryResponse>();
                        } catch (Exception e) {
                            LOG.errorf(e, "Erreur lors du retry pour les statistiques");
                            throw new RuntimeException(e);
                        }
                    },
                    120 // 2 minutes
            );

            totalOrganisations = toutes.size();
            organisationsActives = toutes.stream()
                    .filter(o -> o.getStatut() != null && StatutOrganisationConstants.ACTIVE.equals(o.getStatut()))
                    .count();
            organisationsInactives = totalOrganisations - organisationsActives;

            LOG.infof("Statistiques chargées: total=%d, actives=%d, inactives=%d",
                    totalOrganisations, organisationsActives, organisationsInactives);

        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des statistiques");
            totalOrganisations = 0;
            organisationsActives = 0;
            organisationsInactives = 0;
        }
    }

    // ========== ACTIONS ==========

    /**
     * Prépare la création d'une nouvelle organisation.
     * Protégé contre les postbacks AJAX (polls PrimeFaces, partialSubmit, etc.)
     * pour ne pas réinitialiser le formulaire en cours de saisie.
     */
    public void preparerNouvelleOrganisation() {
        // Ne réinitialiser QUE sur le chargement initial (GET), pas sur les AJAX postbacks
        jakarta.faces.context.FacesContext fc = jakarta.faces.context.FacesContext.getCurrentInstance();
        if (fc != null && fc.isPostback()) {
            return; // AJAX poll ou postback → on ne touche pas au formulaire en cours
        }

        LOG.info("Préparation de la création d'une nouvelle organisation");

        nouvelleOrganisation = new OrganisationResponse();
        nouvelleOrganisation.setStatut(StatutOrganisationConstants.ACTIVE);

        List<TypeReferenceResponse> catalogue = typeCatalogueService.getCatalogueComplet();
        if (!catalogue.isEmpty()) {
            String typeDefaut = catalogue.stream()
                    .filter(t -> !Boolean.FALSE.equals(t.getActif()))
                    .map(TypeReferenceResponse::getCode)
                    .findFirst()
                    .orElse(null);
            nouvelleOrganisation.setTypeOrganisation(typeDefaut);
        }

        nouvelleOrganisation.setDateFondation(java.time.LocalDate.now());
        backupOrganisation = cloneAssociation(nouvelleOrganisation);
    }

    /**
     * Crée une nouvelle organisation avec gestion complète des erreurs et retry.
     */
    public String creerOrganisation() {
        if (nouvelleOrganisation == null) {
            LOG.warn("Tentative de création avec nouvelleOrganisation null");
            errorHandler.showWarning("Erreur", "Aucune organisation à créer");
            return null;
        }

        LOG.infof("Tentative de création d'une organisation: nom=%s, type=%s",
                nouvelleOrganisation.getNom(),
                nouvelleOrganisation.getTypeOrganisation());

        if (!validerOrganisation(nouvelleOrganisation)) {
            return null;
        }

        try {
            OrganisationResponse creee = retryService.executeWithRetrySupplier(
                    () -> organisationService.creer(nouvelleOrganisation),
                    "création d'une organisation");

            LOG.infof("Organisation créée avec succès: id=%s, nom=%s",
                    creee.getId(),
                    creee.getNom());

            cacheService.invalidate("organisations-toutes");

            errorHandler.showSuccess("Succès",
                    "L'organisation '" + creee.getNom() + "' a été créée avec succès");

            nouvelleOrganisation = null;
            backupOrganisation = null;

            chargerOrganisations();
            chargerStatistiques();

            return ViewPaths.ORGANISATION_LISTE + ViewPaths.REDIRECT_SUFFIX;

        } catch (RestClientExceptionMapper.ConflictException e) {
            errorHandler.handleException(e, "lors de la création d'une organisation",
                    "Une organisation avec ce nom existe déjà");
            nouvelleOrganisation = backupOrganisation;
            return null;

        } catch (RestClientExceptionMapper.UnauthorizedException | RestClientExceptionMapper.ForbiddenException e) {
            errorHandler.handleException(e, "lors de la création d'une organisation", null);
            nouvelleOrganisation = backupOrganisation;
            return null;

        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la création d'une organisation", null);
            nouvelleOrganisation = backupOrganisation;
            return null;
        }
    }

    /**
     * Valide une organisation avant création/modification.
     */
    private boolean validerOrganisation(OrganisationResponse org) {
        List<String> errors = new ArrayList<>();

        if (org.getNom() == null || org.getNom().trim().isEmpty()) {
            errors.add("Le nom est obligatoire");
        } else if (org.getNom().trim().length() < 2) {
            errors.add("Le nom doit contenir au moins 2 caractères");
        } else if (org.getNom().trim().length() > 200) {
            errors.add("Le nom ne peut pas dépasser 200 caractères");
        }

        if (org.getEmail() == null || org.getEmail().trim().isEmpty()) {
            errors.add("L'email est obligatoire");
        } else if (!org.getEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
            errors.add("L'email n'est pas valide");
        }

        if (org.getTypeOrganisation() == null || org.getTypeOrganisation().trim().isEmpty()) {
            errors.add("Le type d'organisation est obligatoire");
        }

        if (!errors.isEmpty()) {
            errorHandler.handleValidationErrors(errors, "validation de l'organisation");
            return false;
        }

        return true;
    }

    /**
     * Clone une organisation pour le rollback.
     */
    private OrganisationResponse cloneAssociation(OrganisationResponse org) {
        if (org == null) {
            return null;
        }

        OrganisationResponse clone = new OrganisationResponse();
        clone.setNom(org.getNom());
        clone.setEmail(org.getEmail());
        clone.setTypeOrganisation(org.getTypeOrganisation());
        clone.setStatut(org.getStatut());
        clone.setDescription(org.getDescription());
        clone.setAdresse(org.getAdresse());
        clone.setVille(org.getVille());
        clone.setRegion(org.getRegion());
        clone.setPays(org.getPays());
        clone.setTelephone(org.getTelephone());

        return clone;
    }

    /**
     * Modifie une organisation existante.
     */
    /**
     * Prépare la modification depuis la liste : charge la fiche complète depuis l'API.
     */
    public void preparerModification(OrganisationSummaryResponse org) {
        try {
            organisationSelectionnee = retryService.executeWithRetrySupplier(
                    () -> organisationService.obtenirParId(org.getId()),
                    "chargement de l'organisation pour modification");
        } catch (Exception e) {
            errorHandler.handleException(e, "lors du chargement de l'organisation", null);
            organisationSelectionnee = null;
        }
    }

    public void modifierOrganisation() {
        if (organisationSelectionnee == null || organisationSelectionnee.getId() == null) {
            errorHandler.showWarning("Erreur", "Aucune organisation sélectionnée");
            return;
        }

        LOG.infof("Tentative de modification de l'organisation: id=%s, nom=%s",
                organisationSelectionnee.getId(),
                organisationSelectionnee.getNom());

        if (!validerOrganisation(organisationSelectionnee)) {
            return;
        }

        try {
            OrganisationResponse modifiee = retryService.executeWithRetrySupplier(
                    () -> organisationService.modifier(organisationSelectionnee.getId(), organisationSelectionnee),
                    "modification d'une organisation");

            LOG.infof("Organisation modifiée avec succès: id=%s", modifiee.getId());

            cacheService.invalidate("organisations-toutes");

            errorHandler.showSuccess("Succès",
                    "L'organisation '" + modifiee.getNom() + "' a été modifiée avec succès");

            chargerOrganisations();
            chargerStatistiques();

        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la modification d'une organisation", null);
        }
    }

    /**
     * Prépare la suppression depuis la liste (reçoit un résumé OrganisationSummaryResponse).
     */
    public void preparerSuppression(OrganisationSummaryResponse org) {
        OrganisationResponse full = new OrganisationResponse();
        full.setId(org.getId());
        full.setNom(org.getNom());
        full.setStatut(org.getStatut());
        organisationPourSuppression = full;
    }

    /**
     * Prépare la suppression (ouvre le dialogue de confirmation).
     */
    public void preparerSuppression(OrganisationResponse organisation) {
        organisationPourSuppression = organisation;
    }

    /**
     * Confirme et exécute la suppression après clic sur « Oui » dans le dialogue.
     */
    public void confirmerSuppression() {
        if (organisationPourSuppression == null) {
            errorHandler.showWarning("Erreur", "Aucune organisation à supprimer");
            return;
        }
        OrganisationResponse org = organisationPourSuppression;
        organisationPourSuppression = null;
        supprimerOrganisation(org);
    }

    /**
     * Prépare la bascule de statut depuis la liste (reçoit un résumé OrganisationSummaryResponse).
     */
    public void preparerBasculerStatut(OrganisationSummaryResponse org) {
        OrganisationResponse full = new OrganisationResponse();
        full.setId(org.getId());
        full.setNom(org.getNom());
        full.setStatut(org.getStatut());
        organisationPourStatut = full;
    }

    /**
     * Prépare la bascule de statut (ouvre le dialogue de confirmation).
     */
    public void preparerBasculerStatut(OrganisationResponse organisation) {
        organisationPourStatut = organisation;
    }

    /**
     * Confirme et exécute la bascule de statut après clic sur « Oui » dans le dialogue.
     */
    public void confirmerBasculerStatut() {
        if (organisationPourStatut == null) {
            return;
        }
        OrganisationResponse org = organisationPourStatut;
        organisationPourStatut = null;
        basculerStatutOrganisation(org);
    }

    /**
     * Supprime une organisation.
     */
    public void supprimerOrganisation(OrganisationResponse organisation) {
        if (organisation == null || organisation.getId() == null) {
            errorHandler.showWarning("Erreur", "Aucune organisation sélectionnée");
            return;
        }

        try {
            retryService.executeWithRetry(
                    () -> {
                        organisationService.supprimer(organisation.getId());
                        return null;
                    },
                    "suppression d'une organisation");

            cacheService.invalidate("organisations-toutes");

            errorHandler.showSuccess("Succès",
                    "Organisation '" + organisation.getNom() + "' supprimée avec succès");

            chargerOrganisations();
            chargerStatistiques();

        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la suppression d'une organisation", null);
        }
    }

    /**
     * Active une organisation.
     */
    public void activerOrganisation(OrganisationResponse organisation) {
        if (organisation == null || organisation.getId() == null) {
            errorHandler.showWarning("Erreur", "Aucune organisation sélectionnée");
            return;
        }

        try {
            retryService.executeWithRetrySupplier(
                    () -> organisationService.activer(organisation.getId()),
                    "activation d'une organisation");

            cacheService.invalidate("organisations-toutes");

            errorHandler.showSuccess("Succès", "Organisation activée avec succès");

            chargerOrganisations();
            chargerStatistiques();

        } catch (Exception e) {
            errorHandler.handleException(e, "lors de l'activation d'une organisation", null);
        }
    }

    /**
     * Suspend une organisation.
     */
    public void desactiverOrganisation(OrganisationResponse organisation) {
        if (organisation == null || organisation.getId() == null) {
            errorHandler.showWarning("Erreur", "Aucune organisation sélectionnée");
            return;
        }

        try {
            retryService.executeWithRetrySupplier(
                    () -> organisationService.suspendre(organisation.getId()),
                    "suspension d'une organisation");

            cacheService.invalidate("organisations-toutes");

            errorHandler.showSuccess("Succès", "Organisation suspendue avec succès");

            chargerOrganisations();
            chargerStatistiques();

        } catch (Exception e) {
            errorHandler.handleException(e, "lors de la suspension d'une organisation", null);
        }
    }

    /**
     * Bascule le statut d'une organisation entre ACTIVE et INACTIVE.
     */
    public void basculerStatutOrganisation(OrganisationResponse organisation) {
        if (organisation == null || organisation.getStatut() == null) {
            return;
        }

        String statutActuel = organisation.getStatut();
        if (StatutOrganisationConstants.ACTIVE.equals(statutActuel)) {
            desactiverOrganisation(organisation);
        } else {
            activerOrganisation(organisation);
        }
    }

    /**
     * Recherche les organisations dont le nom contient la requête fournie.
     * Utilisée par p:autoComplete pour la recherche d'organisation parente.
     */
    public List<OrganisationSummaryResponse> rechercherOrganisations(String query) {
        if (query == null || query.trim().isEmpty()) {
            return List.of();
        }
        try {
            PagedResponse<OrganisationSummaryResponse> response = organisationService.rechercher(
                    query, null, null, null, null, 0, 100);
            List<OrganisationSummaryResponse> resultats = (response != null && response.getData() != null) ? response.getData()
                    : new ArrayList<OrganisationSummaryResponse>();
            LOG.infof("Recherche d'organisations pour '%s': %d résultat(s)", query, resultats.size());
            return resultats;
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la recherche d'organisations pour '%s'", query);
            return List.of();
        }
    }

    /**
     * Autocomplétion pour les principales villes d'Afrique de l'Ouest et Centrale.
     */
    public List<String> completerVilles(String query) {
        List<String> villes = List.of(
                // Côte d'Ivoire
                "Abidjan", "Bouaké", "Daloa", "Korhogo", "San-Pédro",
                "Yamoussoukro", "Man", "Divo", "Gagnoa", "Abengourou",
                "Grand-Bassam", "Bingerville",
                // Sénégal
                "Dakar", "Thiès", "Saint-Louis", "Kaolack", "Ziguinchor",
                "Rufisque", "Touba", "Mbour", "Diourbel", "Tambacounda",
                // Mali
                "Bamako", "Sikasso", "Mopti", "Koutiala", "Ségou",
                "Kayes", "Gao", "Tombouctou",
                // Burkina Faso
                "Ouagadougou", "Bobo-Dioulasso", "Koudougou", "Banfora",
                "Ouahigouya", "Kaya",
                // Guinée
                "Conakry", "Kankan", "Kindia", "Nzérékoré", "Labé",
                // Togo
                "Lomé", "Sokodé", "Kara", "Kpalimé", "Atakpamé",
                // Bénin
                "Cotonou", "Porto-Novo", "Parakou", "Abomey-Calavi", "Bohicon",
                // Niger
                "Niamey", "Zinder", "Maradi", "Agadez", "Tahoua",
                // Cameroun
                "Douala", "Yaoundé", "Bafoussam", "Garoua", "Maroua",
                // Gabon
                "Libreville", "Port-Gentil", "Franceville",
                // Congo
                "Brazzaville", "Pointe-Noire",
                // RD Congo
                "Kinshasa", "Lubumbashi", "Mbuji-Mayi", "Kisangani",
                // Maroc
                "Casablanca", "Rabat", "Marrakech", "Fès", "Tanger", "Agadir"
        );
        if (query == null || query.trim().isEmpty()) {
            return villes;
        }
        String queryLower = query.toLowerCase();
        return villes.stream()
                .filter(ville -> ville.toLowerCase().contains(queryLower))
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * Autocomplétion pour les régions d'Afrique de l'Ouest et Centrale.
     */
    public List<String> completerRegions(String query) {
        List<String> regions = List.of(
                // Côte d'Ivoire
                "Lagunes", "Haut-Sassandra", "Savanes", "Vallée du Bandama",
                "Gbêkê", "Nawa", "Tonkpi", "Poro", "Sud-Comoé",
                // Sénégal
                "Dakar", "Thiès", "Diourbel", "Saint-Louis", "Ziguinchor",
                "Kaolack", "Fatick", "Louga", "Matam", "Tambacounda",
                // Mali
                "Bamako", "Sikasso", "Mopti", "Ségou", "Kayes", "Koulikoro",
                // Burkina Faso
                "Centre", "Hauts-Bassins", "Boucle du Mouhoun", "Sahel",
                // Guinée
                "Conakry", "Kindia", "Nzérékoré", "Kankan", "Faranah",
                // Togo
                "Maritime", "Plateaux", "Centrale", "Kara", "Savanes",
                // Bénin
                "Littoral", "Atlantique", "Ouémé", "Borgou", "Zou",
                // Cameroun
                "Centre", "Littoral", "Ouest", "Nord", "Extrême-Nord",
                // Maroc
                "Casablanca-Settat", "Rabat-Salé-Kénitra", "Marrakech-Safi",
                "Fès-Meknès", "Tanger-Tétouan-Al Hoceïma"
        );
        if (query == null || query.trim().isEmpty()) {
            return regions;
        }
        String queryLower = query.toLowerCase();
        return regions.stream()
                .filter(region -> region.toLowerCase().contains(queryLower))
                .collect(java.util.stream.Collectors.toList());
    }

    /**
     * Recharge les données (invalide les caches et recharge).
     */
    public void recharger() {
        LOG.info("Rechargement des données");

        cacheService.invalidate("organisations-toutes");

        chargerOrganisations();
        chargerStatistiques();

        errorHandler.showInfo("Données rechargées", "Les données ont été mises à jour");
    }

    /**
     * Applique les filtres aux organisations.
     */
    public void appliquerFiltres() {
        LOG.debugf("Application des filtres: recherche=%s, statut=%s, type=%s, region=%s",
                rechercheGlobale, filtreStatut, filtreType, filtreRegion);

        if (organisations == null || organisations.isEmpty()) {
            organisationsFiltrees = new ArrayList<>();
            return;
        }

        organisationsFiltrees = organisations.stream()
                .filter(org -> {
                    if (rechercheGlobale != null && !rechercheGlobale.trim().isEmpty()) {
                        String recherche = rechercheGlobale.toLowerCase();
                        return (org.getNom() != null && org.getNom().toLowerCase().contains(recherche)) ||
                                (org.getNomCourt() != null && org.getNomCourt().toLowerCase().contains(recherche)) ||
                                (org.getTypeOrganisationLibelle() != null
                                        && org.getTypeOrganisationLibelle().toLowerCase().contains(recherche));
                    }
                    return true;
                })
                .filter(org -> {
                    if (filtreStatut != null && !filtreStatut.trim().isEmpty()) {
                        return filtreStatut.equals(org.getStatut());
                    }
                    return true;
                })
                .filter(org -> {
                    if (filtreType != null && !filtreType.trim().isEmpty()) {
                        return filtreType.equals(org.getTypeOrganisation());
                    }
                    return true;
                })
                // DISABLED: OrganisationSummaryResponse doesn't have region field
                // TODO: Add region to OrganisationSummaryResponse or load full Response for region filter
                /*.filter(org -> {
                    if (filtreRegion != null && !filtreRegion.trim().isEmpty()) {
                        return filtreRegion.equals(org.getRegion());
                    }
                    return true;
                })*/
                .collect(java.util.stream.Collectors.toList());

        LOG.debugf("Filtres appliqués: %d organisations sur %d", organisationsFiltrees.size(), organisations.size());
    }

    /**
     * Réinitialise les filtres.
     */
    public void reinitialiserFiltres() {
        rechercheGlobale = null;
        filtreStatut = null;
        filtreType = null;
        filtreRegion = null;
        appliquerFiltres();
        errorHandler.showInfo("Filtres réinitialisés", "Tous les filtres ont été réinitialisés");
    }

    // ========== GETTERS/SETTERS ==========

    public List<OrganisationSummaryResponse> getOrganisations() {
        return organisations;
    }

    public void setOrganisations(List<OrganisationSummaryResponse> organisations) {
        this.organisations = organisations;
    }

    public List<OrganisationSummaryResponse> getOrganisationsFiltrees() {
        if (organisationsFiltrees == null) {
            organisationsFiltrees = new ArrayList<>(organisations);
        }
        return organisationsFiltrees;
    }

    public void setOrganisationsFiltrees(List<OrganisationSummaryResponse> organisationsFiltrees) {
        this.organisationsFiltrees = organisationsFiltrees;
    }

    public OrganisationResponse getOrganisationSelectionnee() {
        return organisationSelectionnee;
    }

    public void setOrganisationSelectionnee(OrganisationResponse organisationSelectionnee) {
        this.organisationSelectionnee = organisationSelectionnee;
    }

    public OrganisationResponse getNouvelleOrganisation() {
        if (nouvelleOrganisation == null) {
            preparerNouvelleOrganisation();
        }
        return nouvelleOrganisation;
    }

    public void setNouvelleOrganisation(OrganisationResponse nouvelleOrganisation) {
        this.nouvelleOrganisation = nouvelleOrganisation;
    }

    public List<TypeReferenceResponse> getTypesCatalogue() {
        return typeCatalogueService.getCatalogueComplet();
    }

    public long getTotalOrganisations() {
        return totalOrganisations;
    }

    public long getOrganisationsActives() {
        return organisationsActives;
    }

    public long getOrganisationsInactives() {
        return organisationsInactives;
    }

    public long getTauxActivite() {
        if (totalOrganisations == 0) return 0;
        return (organisationsActives * 100) / totalOrganisations;
    }

    public String getRechercheGlobale() {
        return rechercheGlobale;
    }

    public void setRechercheGlobale(String rechercheGlobale) {
        this.rechercheGlobale = rechercheGlobale;
    }

    public String getFiltreStatut() {
        return filtreStatut;
    }

    public void setFiltreStatut(String filtreStatut) {
        this.filtreStatut = filtreStatut;
    }

    public String getFiltreType() {
        return filtreType;
    }

    public void setFiltreType(String filtreType) {
        this.filtreType = filtreType;
    }

    public String getFiltreRegion() {
        return filtreRegion;
    }

    public void setFiltreRegion(String filtreRegion) {
        this.filtreRegion = filtreRegion;
    }

    // ========== MÉTHODES UTILITAIRES ==========

    public boolean estActive(OrganisationResponse organisation) {
        return organisation != null &&
                organisation.getStatut() != null &&
                StatutOrganisationConstants.ACTIVE.equals(organisation.getStatut());
    }

    public String getStatutActive() {
        return StatutOrganisationConstants.ACTIVE;
    }

    public String getStatutInactive() {
        return StatutOrganisationConstants.INACTIVE;
    }

    public String getStatutSuspendue() {
        return StatutOrganisationConstants.SUSPENDUE;
    }

    public String getStatutDissoute() {
        return StatutOrganisationConstants.DISSOUTE;
    }

    /**
     * Retourne la liste des statuts pour les SelectItem.
     */
    public List<SelectItem> getStatutsSelectItems() {
        List<SelectItem> items = new ArrayList<>();
        items.add(new SelectItem("", "Tous les statuts"));
        items.add(new SelectItem(StatutOrganisationConstants.ACTIVE, "Active"));
        items.add(new SelectItem(StatutOrganisationConstants.INACTIVE, "Inactive"));
        items.add(new SelectItem(StatutOrganisationConstants.SUSPENDUE, "Suspendue"));
        items.add(new SelectItem(StatutOrganisationConstants.DISSOUTE, "Dissoute"));
        return items;
    }

    public List<SelectItem> getTypesSelectItems() {
        return typeCatalogueService.getSelectItems("Tous les types");
    }

    public List<SelectItem> getTypesSelectItemsForForm() {
        return typeCatalogueService.getSelectItems("Sélectionner...");
    }
}
