package dev.lions.unionflow.client.security;

import dev.lions.unionflow.client.view.UserSession;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * Service de vérification des permissions utilisateur
 *
 * SÉCURITÉ:
 * - Support des rôles multiples
 * - Hiérarchie de permissions (SUPER_ADMIN > ADMIN > GESTIONNAIRE > MEMBER)
 * - Vérification granulaire par fonctionnalité
 *
 * @author UnionFlow Team
 * @version 2.0
 */
@Named("permissionChecker")
@RequestScoped
public class PermissionChecker implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    private UserSession userSession;

    // Hiérarchie des rôles plateforme (de plus privilégié à moins privilégié)
    // Aligné avec la constitution UnionFlow v2.11 — codes Keycloak
    private static final List<String> ROLE_HIERARCHY = Arrays.asList(
        "SUPERADMIN",       // niveau 10 — plateforme
        "SUPER_ADMIN",      // alias rétro-compatible
        "ORGADMIN",         // niveau 20 — plateforme
        "ADMIN_ORGANISATION", // alias rétro-compatible
        "ADMIN",            // alias rétro-compatible
        "MODERATOR",        // niveau 30 — plateforme
        "MODERATEUR",       // alias français
        "CONSULTANT",       // niveau 45 — lecture étendue
        "GESTIONNAIRE_RH",  // niveau 30 — RH
        "ACTIVEMEMBER",     // niveau 40 — plateforme
        "MEMBRE_ACTIF",     // alias
        "TRESORIER",        // rôle fonctionnel
        "SECRETAIRE",       // rôle fonctionnel
        "SIMPLEMEMBER",     // niveau 50 — plateforme
        "MEMBRE",           // alias
        "MEMBER",           // alias anglais
        "VISITOR",          // niveau 60 — lecture seule
        "VISITEUR"          // alias français
    );

    /**
     * Vérifie si l'utilisateur possède un rôle spécifique
     * SÉCURITÉ: Support des rôles multiples
     */
    public boolean hasRole(String role) {
        if (userSession == null || !userSession.isAuthenticated()) {
            return false;
        }

        List<String> userRoles = userSession.getRoles();
        if (userRoles == null || userRoles.isEmpty()) {
            return false;
        }

        return userRoles.contains(role);
    }

    /**
     * Vérifie si l'utilisateur possède au moins un des rôles spécifiés
     * SÉCURITÉ: Support des rôles multiples
     */
    public boolean hasAnyRole(String... roles) {
        if (userSession == null || !userSession.isAuthenticated()) {
            return false;
        }

        List<String> userRoles = userSession.getRoles();
        if (userRoles == null || userRoles.isEmpty()) {
            return false;
        }

        for (String role : roles) {
            if (userRoles.contains(role)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Vérifie si l'utilisateur possède TOUS les rôles spécifiés
     * SÉCURITÉ: Vérification stricte pour permissions combinées
     */
    public boolean hasAllRoles(String... roles) {
        if (userSession == null || !userSession.isAuthenticated()) {
            return false;
        }

        List<String> userRoles = userSession.getRoles();
        if (userRoles == null || userRoles.isEmpty()) {
            return false;
        }

        for (String role : roles) {
            if (!userRoles.contains(role)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Vérifie si l'utilisateur a un niveau de privilège au moins égal au rôle spécifié
     * SÉCURITÉ: Hiérarchie de rôles (SUPER_ADMIN peut tout faire)
     */
    public boolean hasRoleOrHigher(String role) {
        if (userSession == null || !userSession.isAuthenticated()) {
            return false;
        }

        List<String> userRoles = userSession.getRoles();
        if (userRoles == null || userRoles.isEmpty()) {
            return false;
        }

        int requiredLevel = ROLE_HIERARCHY.indexOf(role);
        if (requiredLevel == -1) {
            return false; // Rôle inconnu
        }

        // Vérifier si l'utilisateur a un rôle de niveau égal ou supérieur
        for (String userRole : userRoles) {
            int userLevel = ROLE_HIERARCHY.indexOf(userRole);
            if (userLevel != -1 && userLevel <= requiredLevel) {
                return true; // Niveau supérieur ou égal trouvé
            }
        }

        return false;
    }
    
    // ── Vérifications basées sur les rôles plateforme ──────────────────────────

    public boolean canManageMembers() {
        return userSession != null && (userSession.isAdmin() || userSession.isModerateur());
    }

    public boolean canValidateMembers() {
        return userSession != null && userSession.isAdmin();
    }

    public boolean canManageFinances() {
        return userSession != null && (userSession.isAdmin() || hasAnyRole("TRESORIER", "TRESORIER_ADJOINT"));
    }

    public boolean canManageEvents() {
        return userSession != null && (userSession.isAdmin() || userSession.isModerateur()
                || hasRole("RESPONSABLE_EVENEMENTS"));
    }

    public boolean canManageAides() {
        return userSession != null && (userSession.isAdmin() || userSession.isModerateur());
    }

    public boolean canViewReports() {
        return userSession != null && (userSession.isAdmin() || userSession.isModerateur()
                || userSession.isConsultant() || hasRole("TRESORIER"));
    }

    public boolean canManageSubscription() {
        return userSession != null && userSession.isAdmin();
    }

    public boolean canManageOrganization() {
        return userSession != null && userSession.isAdmin();
    }

    public boolean canAccessSuperAdmin() {
        return userSession != null && userSession.isSuperAdmin();
    }

    public boolean canInviteMembers() {
        return userSession != null && (userSession.isAdmin() || userSession.isModerateur()
                || hasRole("RESPONSABLE_MEMBRES"));
    }

    public boolean canManageRoles() {
        return userSession != null && (userSession.isSuperAdmin() || userSession.isAdmin());
    }
    
    // Vérifications basées sur les fonctionnalités du forfait
    public boolean isFeatureEnabled(String feature) {
        // Cette méthode vérifiera si la fonctionnalité est incluse dans le forfait souscrit
        // Pour l'instant, simulation basée sur des rôles
        
        switch (feature.toLowerCase()) {
            case "gestion_membres":
                return true; // Toujours disponible
                
            case "gestion_cotisations":
                return true; // Toujours disponible
                
            case "gestion_evenements":
                return !hasRole("MEMBER"); // Pas pour les membres simples
                
            case "gestion_aides":
                return hasAnyRole("ADMIN", "GESTIONNAIRE_AIDE");
                
            case "rapports_avances":
                return hasAnyRole("ADMIN", "SUPER_ADMIN");
                
            case "integration_paiement":
                return hasAnyRole("ADMIN", "TRESORIER");
                
            case "notifications_sms":
                return hasAnyRole("ADMIN", "SUPER_ADMIN");
                
            case "gestion_documents":
                return hasAnyRole("ADMIN", "GESTIONNAIRE_MEMBRE");
                
            case "support_prioritaire":
                return hasAnyRole("ADMIN", "SUPER_ADMIN");
                
            case "personnalisation_avancee":
                return hasRole("SUPER_ADMIN");
                
            default:
                return false;
        }
    }
    
    // Vérifications pour l'interface utilisateur
    public boolean showCreateMemberButton() {
        return canManageMembers() && isFeatureEnabled("gestion_membres");
    }
    
    public boolean showValidateMemberButton() {
        return canValidateMembers() && isFeatureEnabled("gestion_membres");
    }
    
    public boolean showFinancialSection() {
        return canManageFinances() && isFeatureEnabled("gestion_cotisations");
    }
    
    public boolean showEventsSection() {
        return canManageEvents() && isFeatureEnabled("gestion_evenements");
    }
    
    public boolean showAidesSection() {
        return canManageAides() && isFeatureEnabled("gestion_aides");
    }
    
    public boolean showReportsSection() {
        return canViewReports() && isFeatureEnabled("rapports_avances");
    }
    
    public boolean showSubscriptionManagement() {
        return canManageSubscription();
    }
    
    public boolean showAdvancedSettings() {
        return canManageOrganization() && isFeatureEnabled("personnalisation_avancee");
    }
    
    public boolean showSuperAdminFeatures() {
        return canAccessSuperAdmin();
    }
    
    // Vérifications spécifiques aux actions
    public boolean canCreateEvent() {
        return canManageEvents() && isFeatureEnabled("gestion_evenements");
    }
    
    public boolean canProcessAideRequest() {
        return canManageAides() && isFeatureEnabled("gestion_aides");
    }
    
    public boolean canExportData() {
        return canViewReports() && isFeatureEnabled("rapports_avances");
    }
    
    public boolean canSendNotifications() {
        return canManageMembers() && (isFeatureEnabled("notifications_email") || isFeatureEnabled("notifications_sms"));
    }
    
    public boolean canManageDocuments() {
        return canManageMembers() && isFeatureEnabled("gestion_documents");
    }
    
    // Vérifications pour les limites
    public boolean canAddNewMember() {
        if (!canManageMembers()) {
            return false;
        }
        
        // Vérifier le quota de membres (sera implémenté avec SouscriptionBean)
        // Pour l'instant, toujours vrai si on a les permissions
        return true;
    }
    
    // Méthodes utilitaires pour l'affichage conditionnel
    public String getRoleBasedStyleClass() {
        if (!userSession.isAuthenticated()) {
            return "guest-mode";
        }

        // Déterminer le style basé sur le rôle le plus privilégié
        if (hasRole("SUPER_ADMIN")) {
            return "super-admin-mode";
        } else if (hasAnyRole("ADMIN", "ADMIN_ORGANISATION")) {
            return "admin-mode";
        } else if (hasAnyRole("GESTIONNAIRE_MEMBRE", "GESTIONNAIRE_EVENEMENT", "GESTIONNAIRE_AIDE", "GESTIONNAIRE_FINANCE")) {
            return "gestionnaire-mode";
        } else if (hasRole("TRESORIER")) {
            return "tresorier-mode";
        } else {
            return "member-mode";
        }
    }

    /**
     * Retourne le rôle le plus privilégié de l'utilisateur
     * SÉCURITÉ: Basé sur la hiérarchie définie
     */
    public String getHighestRole() {
        if (userSession == null || !userSession.isAuthenticated()) {
            return null;
        }

        List<String> userRoles = userSession.getRoles();
        if (userRoles == null || userRoles.isEmpty()) {
            return null;
        }

        // Retourner le premier rôle trouvé dans la hiérarchie
        for (String hierarchyRole : ROLE_HIERARCHY) {
            if (userRoles.contains(hierarchyRole)) {
                return hierarchyRole;
            }
        }

        // Si aucun rôle connu, retourner le premier de la liste
        return userRoles.get(0);
    }
    
    public String getPermissionMessage(String action) {
        return "Vous n'avez pas les permissions nécessaires pour " + action;
    }
    
    // Getters pour utilisation dans les expressions EL
    public boolean isAuthenticated() {
        return userSession != null && userSession.isAuthenticated();
    }
    
    public boolean isSuperAdmin() {
        return hasRole("SUPER_ADMIN");
    }
    
    public boolean isAdmin() {
        return hasRole("ADMIN");
    }
    
    public boolean isMember() {
        return hasAnyRole("MEMBRE", "MEMBER", "SIMPLEMEMBER", "ACTIVEMEMBER");
    }

    public boolean isModerateur() {
        return userSession != null && userSession.isModerateur();
    }

    public boolean isConsultant() {
        return userSession != null && userSession.isConsultant();
    }

    public boolean isGestionnaireRh() {
        return userSession != null && userSession.isGestionnaireRh();
    }

    public boolean isVisiteur() {
        return userSession != null && userSession.isVisiteur();
    }

    public boolean isGestionnaire() {
        return isModerateur() || isConsultant() || isGestionnaireRh();
    }

    public boolean isTresorier() {
        return hasRole("TRESORIER");
    }

    /** Retourne true si l'utilisateur a accès à une fonctionnalité métier selon son rôle. */
    public boolean canAccessBusinessFeature(String feature) {
        if (userSession == null || !userSession.isAuthenticated()) {
            return false;
        }
        return switch (feature.toUpperCase()) {
            case "TONTINE"         -> hasAnyRole("TONTINE_MANAGER", "TONTINE_COLLECTOR") || userSession.isAdmin();
            case "CREDIT"          -> hasAnyRole("MUTUELLE_RESP", "CREDIT_ANALYSTE")      || userSession.isAdmin();
            case "EPARGNE"         -> hasAnyRole("MUTUELLE_RESP", "EPARGNE_MANAGER")       || userSession.isAdmin();
            case "AGRICULTURE"     -> hasAnyRole("COOP_RESP")                              || userSession.isAdmin();
            case "PROJETS_ONG"     -> hasAnyRole("ONG_RESP", "PROJET_MANAGER")             || userSession.isAdmin();
            case "CULTE_DONS"      -> hasAnyRole("CULTE_RESP", "PASTEUR", "DIACRE")        || userSession.isAdmin();
            case "VOTES"           -> hasAnyRole("VOTE_RESP")                              || userSession.isAdmin();
            case "COLLECTE_FONDS"  -> hasAnyRole("COLLECTE_RESP")                         || userSession.isAdmin();
            case "REGISTRE_AGREMENT"-> hasAnyRole("REGISTRE_RESP")                        || userSession.isAdmin();
            default -> userSession.isAdmin() || userSession.isModerateur();
        };
    }
}
