package dev.lions.unionflow.client.bean;

import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.jboss.logging.Logger;

import java.io.IOException;

/**
 * Bean centralisé pour la sécurisation des pages basée sur les rôles.
 * Fournit des méthodes réutilisables pour vérifier l'accès et rediriger si nécessaire.
 *
 * <p>Principe DRY/WOU : Une seule implémentation de la logique de sécurité,
 * réutilisée par toutes les pages via un composant Facelet.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-02
 */
@Named("pageSecurityBean")
@ApplicationScoped
public class PageSecurityBean {

    private static final Logger LOG = Logger.getLogger(PageSecurityBean.class);
    private static final String ACCESS_DENIED_PAGE = "/pages/secure/access-denied.xhtml";

    @Inject
    SecurityIdentity securityIdentity;

    @Inject
    MenuBean menuBean;

    /**
     * Vérifie si l'utilisateur a le droit d'accéder à une page donnée.
     * Si non autorisé, redirige vers la page access-denied.
     *
     * @param allowedRoles Rôles autorisés séparés par des virgules (ex: "ADMIN,TRESORIER")
     * @return true si autorisé, false sinon (après redirection)
     */
    public boolean checkAccessOrRedirect(String allowedRoles) {
        if (allowedRoles == null || allowedRoles.trim().isEmpty()) {
            // Aucune restriction = accès autorisé pour tous les utilisateurs authentifiés
            return !securityIdentity.isAnonymous();
        }

        String[] roles = allowedRoles.split(",");
        boolean hasAccess = false;

        for (String role : roles) {
            String trimmedRole = role.trim();
            if (hasRole(trimmedRole)) {
                hasAccess = true;
                break;
            }
        }

        if (!hasAccess) {
            LOG.warnf("Accès refusé pour l'utilisateur %s à une page nécessitant les rôles: %s",
                    securityIdentity.getPrincipal().getName(), allowedRoles);
            redirectToAccessDenied();
            return false;
        }

        return true;
    }

    /**
     * Vérifie si l'utilisateur possède un rôle spécifique.
     *
     * @param role Le rôle à vérifier
     * @return true si l'utilisateur a ce rôle
     */
    private boolean hasRole(String role) {
        return switch (role) {
            case "SUPER_ADMIN" -> menuBean.isSuperAdmin();
            case "ADMIN_ORGANISATION", "ADMIN" -> menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "TRESORIER" -> menuBean.isTresorier() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "SECRETAIRE" -> menuBean.isSecretaire() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "RESPONSABLE_SOCIAL" -> menuBean.isResponsableSocial() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "RESPONSABLE_EVENEMENTS" -> menuBean.isResponsableEvenements() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "RESPONSABLE_CREDIT" -> menuBean.isResponsableCredit() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "MEMBRE_BUREAU" -> menuBean.isMembreBureau() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "MEMBRE_ACTIF" -> menuBean.isMembreActif() || menuBean.isMembreBureau() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "MEMBRE_SIMPLE" -> menuBean.isMembreSimple() || menuBean.isMembreActif() || menuBean.isMembreBureau() || menuBean.isAdminOrganisation() || menuBean.isSuperAdmin();
            case "ALL" -> !securityIdentity.isAnonymous(); // Tous les utilisateurs authentifiés
            default -> {
                LOG.warnf("Rôle inconnu: %s", role);
                yield false;
            }
        };
    }

    /**
     * Redirige vers la page d'accès refusé.
     */
    private void redirectToAccessDenied() {
        try {
            FacesContext ctx = FacesContext.getCurrentInstance();
            if (ctx != null && !ctx.getResponseComplete()) {
                String contextPath = ctx.getExternalContext().getRequestContextPath();
                ctx.getExternalContext().redirect(contextPath + ACCESS_DENIED_PAGE);
                ctx.responseComplete();
            }
        } catch (IOException e) {
            LOG.error("Erreur lors de la redirection vers access-denied", e);
        }
    }

    // ═══════════════════════════════════════════════════════════════════════
    // Méthodes helper pour vérifications rapides (utilisées dans les pages)
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Vérifie si l'utilisateur peut gérer les membres.
     * @return true si SECRETAIRE, ADMIN, ou SUPER_ADMIN
     */
    public boolean canManageMembers() {
        return hasRole("SECRETAIRE");
    }

    /**
     * Vérifie si l'utilisateur peut gérer les finances.
     * @return true si TRESORIER, ADMIN, ou SUPER_ADMIN
     */
    public boolean canManageFinances() {
        return hasRole("TRESORIER");
    }

    /**
     * Vérifie si l'utilisateur peut gérer les événements.
     * @return true si RESPONSABLE_EVENEMENTS, SECRETAIRE, ADMIN, ou SUPER_ADMIN
     */
    public boolean canManageEvents() {
        return hasRole("RESPONSABLE_EVENEMENTS");
    }

    /**
     * Vérifie si l'utilisateur peut gérer les aides sociales.
     * @return true si RESPONSABLE_SOCIAL, ADMIN, ou SUPER_ADMIN
     */
    public boolean canManageSocialAid() {
        return hasRole("RESPONSABLE_SOCIAL");
    }

    /**
     * Vérifie si l'utilisateur peut voir les rapports financiers.
     * @return true si TRESORIER, SECRETAIRE, ADMIN, ou SUPER_ADMIN
     */
    public boolean canViewFinancialReports() {
        return hasRole("TRESORIER") || hasRole("SECRETAIRE");
    }

    /**
     * Vérifie si l'utilisateur peut exporter des données.
     * @return true si TRESORIER, SECRETAIRE, ADMIN, ou SUPER_ADMIN
     */
    public boolean canExportData() {
        return hasRole("TRESORIER") || hasRole("SECRETAIRE");
    }

    /**
     * Vérifie si l'utilisateur est un simple membre (MEMBRE_ACTIF uniquement).
     * @return true si MEMBRE_ACTIF mais pas d'autre rôle administratif
     */
    public boolean isSimpleMember() {
        return menuBean.isMembreActif() &&
                !menuBean.isSecretaire() &&
                !menuBean.isTresorier() &&
                !menuBean.isResponsableSocial() &&
                !menuBean.isResponsableEvenements() &&
                !menuBean.isResponsableCredit() &&
                !menuBean.isMembreBureau() &&
                !menuBean.isAdminOrganisation() &&
                !menuBean.isSuperAdmin();
    }
}
