package com.gbcm.client.beans.auth;

import java.io.Serializable;
import java.util.Set;
import java.util.logging.Logger;

import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.OidcSession;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named("authBean")
@SessionScoped
public class AuthBean implements Serializable {

    private static final Logger logger = Logger.getLogger(AuthBean.class.getName());

    @Inject
    SecurityIdentity securityIdentity;

    @Inject
    OidcSession oidcSession;

    @Inject
    @IdToken
    JsonWebToken idToken;

    /**
     * Vérifie si l'utilisateur est authentifié
     */
    public boolean isAuthenticated() {
        return securityIdentity != null && !securityIdentity.isAnonymous();
    }

    /**
     * Obtient le nom d'utilisateur
     */
    public String getUsername() {
        if (!isAuthenticated()) {
            return "Invité";
        }
        return securityIdentity.getPrincipal().getName();
    }

    /**
     * Obtient le nom d'utilisateur (alias pour le topbar)
     */
    public String getUserName() {
        return getFullName();
    }

    /**
     * Obtient l'email de l'utilisateur depuis le token ID
     */
    public String getEmail() {
        if (!isAuthenticated() || idToken == null) {
            return "guest@example.com";
        }

        String email = idToken.getClaim("email");
        return email != null ? email : getUsername();
    }

    /**
     * Obtient l'email de l'utilisateur (alias pour le topbar)
     */
    public String getUserEmail() {
        return getEmail();
    }

    /**
     * Obtient l'avatar de l'utilisateur
     */
    public String getUserAvatar() {
        if (!isAuthenticated() || idToken == null) {
            return "images/avatar-gbcm.png";
        }

        // Vérifier s'il y a une photo dans le token
        String picture = idToken.getClaim("picture");
        if (picture != null && !picture.trim().isEmpty()) {
            return picture;
        }

        // Avatar par défaut GBCM
        return "images/avatar-gbcm.png";
    }

    /**
     * Obtient le nom complet de l'utilisateur
     */
    public String getFullName() {
        if (!isAuthenticated() || idToken == null) {
            return "Utilisateur Invité";
        }
        
        String givenName = idToken.getClaim("given_name");
        String familyName = idToken.getClaim("family_name");
        
        if (givenName != null && familyName != null) {
            return givenName + " " + familyName;
        }
        
        String name = idToken.getClaim("name");
        return name != null ? name : getUsername();
    }

    /**
     * Obtient les rôles de l'utilisateur
     */
    public Set<String> getRoles() {
        if (!isAuthenticated()) {
            return Set.of("GUEST");
        }
        return securityIdentity.getRoles();
    }

    /**
     * Vérifie si l'utilisateur a un rôle spécifique
     */
    public boolean hasRole(String role) {
        return isAuthenticated() && securityIdentity.hasRole(role);
    }

    /**
     * Vérifie si l'utilisateur est administrateur
     */
    public boolean isAdmin() {
        return hasRole("ADMIN");
    }

    /**
     * Vérifie si l'utilisateur est manager
     */
    public boolean isManager() {
        return hasRole("MANAGER");
    }

    /**
     * Vérifie si l'utilisateur est coach
     */
    public boolean isCoach() {
        return hasRole("COACH");
    }

    /**
     * Vérifie si l'utilisateur est client
     */
    public boolean isClient() {
        return hasRole("CLIENT");
    }

    /**
     * Vérifie si l'utilisateur est prospect
     */
    public boolean isProspect() {
        return hasRole("PROSPECT");
    }

    /**
     * Obtient le rôle principal de l'utilisateur
     */
    public String getPrimaryRole() {
        if (!isAuthenticated()) {
            return "GUEST";
        }
        
        Set<String> roles = getRoles();
        if (roles.contains("ADMIN")) return "ADMIN";
        if (roles.contains("MANAGER")) return "MANAGER";
        if (roles.contains("COACH")) return "COACH";
        if (roles.contains("CLIENT")) return "CLIENT";
        if (roles.contains("PROSPECT")) return "PROSPECT";
        
        return roles.isEmpty() ? "USER" : roles.iterator().next();
    }

    /**
     * Déconnexion OIDC
     */
    public String logout() {
        try {
            logger.info("Début de la déconnexion OIDC");
            
            if (oidcSession != null) {
                logger.info("Déconnexion de la session OIDC");
                oidcSession.logout().await().indefinitely();
            }
            
            // Invalider la session JSF
            FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
            
            // Message de confirmation
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_INFO, "Déconnexion réussie", 
                    "Vous avez été déconnecté avec succès."));
            
            logger.info("Déconnexion OIDC terminée");
            return "/index?faces-redirect=true";
            
        } catch (Exception e) {
            logger.severe("Erreur lors de la déconnexion OIDC: " + e.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de déconnexion", 
                    "Une erreur s'est produite lors de la déconnexion."));
            return null;
        }
    }

    /**
     * Obtient les informations du token ID pour debug
     */
    public String getTokenInfo() {
        if (!isAuthenticated() || idToken == null) {
            return "Aucun token disponible";
        }

        StringBuilder info = new StringBuilder();
        info.append("Issuer: ").append(idToken.getIssuer()).append("\n");
        info.append("Subject: ").append(idToken.getSubject()).append("\n");
        info.append("Expiration: ").append(idToken.getExpirationTime()).append("\n");
        info.append("Issued At: ").append(idToken.getIssuedAtTime()).append("\n");

        return info.toString();
    }

    /**
     * Obtient les informations détaillées du token pour la page profil
     */
    public TokenInfo getTokenInfoDetails() {
        if (!isAuthenticated() || idToken == null) {
            return new TokenInfo();
        }

        return new TokenInfo(
            idToken.getIssuer(),
            idToken.getSubject(),
            idToken.getAudience() != null ? String.join(", ", idToken.getAudience()) : "N/A",
            idToken.getExpirationTime(),
            idToken.getIssuedAtTime()
        );
    }

    /**
     * Classe interne pour les informations du token
     */
    public static class TokenInfo {
        private String issuer;
        private String subject;
        private String audience;
        private Long expirationTime;
        private Long issuedAt;

        public TokenInfo() {
            this.issuer = "N/A";
            this.subject = "N/A";
            this.audience = "N/A";
            this.expirationTime = 0L;
            this.issuedAt = 0L;
        }

        public TokenInfo(String issuer, String subject, String audience, Long expirationTime, Long issuedAt) {
            this.issuer = issuer;
            this.subject = subject;
            this.audience = audience;
            this.expirationTime = expirationTime;
            this.issuedAt = issuedAt;
        }

        public String getIssuer() { return issuer; }
        public String getSubject() { return subject; }
        public String getAudience() { return audience; }
        public Long getExpirationTime() { return expirationTime; }
        public Long getIssuedAt() { return issuedAt; }
    }

    /**
     * Navigation vers le login
     */
    public String login() {
        return "/login?faces-redirect=true";
    }

    /**
     * Navigation vers le dashboard
     */
    public String dashboard() {
        if (!isAuthenticated()) {
            return login();
        }
        return "/pages/dashboard?faces-redirect=true";
    }

    /**
     * Navigation vers le profil
     */
    public String profile() {
        if (!isAuthenticated()) {
            return login();
        }
        return "/pages/profile?faces-redirect=true";
    }

    /**
     * Navigation vers les clients
     */
    public String clients() {
        if (!isAuthenticated()) {
            return login();
        }
        return "/pages/clients?faces-redirect=true";
    }
}
