package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.dto.auth.LoginResponse;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;

@Named("userSession")
@SessionScoped
public class UserSession implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = Logger.getLogger(UserSession.class.getName());
    
    private String username;
    private boolean authenticated = false;
    private String typeCompte;
    private List<String> roles;
    private List<String> permissions;
    private CurrentUser currentUser;
    private EntiteInfo entite;
    
    public UserSession() {
        // Session par défaut non authentifiée
        clearSession();
    }
    
    public void updateFromLoginResponse(LoginResponse loginResponse) {
        if (loginResponse != null && loginResponse.getUser() != null) {
            LoginResponse.UserInfo userInfo = loginResponse.getUser();
            
            this.authenticated = true;
            this.username = userInfo.getUsername();
            this.typeCompte = userInfo.getTypeCompte();
            this.roles = userInfo.getRoles();
            this.permissions = userInfo.getPermissions();
            
            // Mettre à jour les informations utilisateur
            this.currentUser = new CurrentUser();
            this.currentUser.setId(userInfo.getId());
            this.currentUser.setNom(userInfo.getNom());
            this.currentUser.setPrenom(userInfo.getPrenom());
            this.currentUser.setEmail(userInfo.getEmail());
            this.currentUser.setUsername(userInfo.getUsername());
            
            // Mettre à jour les informations de l'entité
            if (userInfo.getEntite() != null) {
                this.entite = new EntiteInfo();
                this.entite.setId(userInfo.getEntite().getId());
                this.entite.setNom(userInfo.getEntite().getNom());
                this.entite.setType(userInfo.getEntite().getType());
                this.entite.setPays(userInfo.getEntite().getPays());
                this.entite.setVille(userInfo.getEntite().getVille());
            }
            
            LOGGER.info("Session utilisateur mise à jour pour: " + userInfo.getUsername() + 
                       " (Type: " + typeCompte + ")");
        }
    }
    
    public void clearSession() {
        this.authenticated = false;
        this.username = null;
        this.typeCompte = null;
        this.roles = null;
        this.permissions = null;
        this.currentUser = null;
        this.entite = null;
        
        LOGGER.info("Session utilisateur effacée");
    }
    
    // Méthodes de vérification des rôles et permissions
    public boolean hasRole(String role) {
        return roles != null && roles.contains(role);
    }
    
    public boolean hasPermission(String permission) {
        return permissions != null && permissions.contains(permission);
    }
    
    public boolean isSuperAdmin() {
        return "SUPER_ADMIN".equals(typeCompte) || hasRole("SUPER_ADMIN");
    }
    
    public boolean isAdmin() {
        return isSuperAdmin() || "ADMIN_ENTITE".equals(typeCompte) || hasRole("ADMIN_ENTITE");
    }
    
    public boolean isMembre() {
        return "MEMBRE".equals(typeCompte) || hasRole("MEMBRE");
    }
    
    // Méthode pour obtenir le rôle principal
    public String getRole() {
        if (isSuperAdmin()) {
            return "SUPER_ADMIN";
        }
        if (isAdmin()) {
            return "ADMIN";
        }
        if (typeCompte != null) {
            return typeCompte;
        }
        if (roles != null && !roles.isEmpty()) {
            return roles.get(0);
        }
        return "MEMBER";
    }
    
    // Getters et Setters
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public boolean isAuthenticated() {
        return authenticated;
    }
    
    public void setAuthenticated(boolean authenticated) {
        this.authenticated = authenticated;
    }
    
    public String getTypeCompte() {
        return typeCompte;
    }
    
    public void setTypeCompte(String typeCompte) {
        this.typeCompte = typeCompte;
    }
    
    public List<String> getRoles() {
        return roles;
    }
    
    public void setRoles(List<String> roles) {
        this.roles = roles;
    }
    
    public List<String> getPermissions() {
        return permissions;
    }
    
    public void setPermissions(List<String> permissions) {
        this.permissions = permissions;
    }
    
    public CurrentUser getCurrentUser() {
        return currentUser;
    }
    
    public void setCurrentUser(CurrentUser currentUser) {
        this.currentUser = currentUser;
    }
    
    public EntiteInfo getEntite() {
        return entite;
    }
    
    public void setEntite(EntiteInfo entite) {
        this.entite = entite;
    }
    
    // Classes internes
    public static class CurrentUser implements Serializable {
        private Long id;
        private String nom;
        private String prenom;
        private String email;
        private String username;
        
        public String getNomComplet() {
            if (prenom != null && nom != null) {
                return prenom + " " + nom;
            }
            return nom != null ? nom : username;
        }
        
        public String getInitiales() {
            StringBuilder initiales = new StringBuilder();
            if (prenom != null && !prenom.isEmpty()) {
                initiales.append(prenom.charAt(0));
            }
            if (nom != null && !nom.isEmpty()) {
                initiales.append(nom.charAt(0));
            }
            return initiales.toString().toUpperCase();
        }
        
        // Getters et Setters
        public Long getId() {
            return id;
        }
        
        public void setId(Long id) {
            this.id = id;
        }
        
        public String getNom() {
            return nom;
        }
        
        public void setNom(String nom) {
            this.nom = nom;
        }
        
        public String getPrenom() {
            return prenom;
        }
        
        public void setPrenom(String prenom) {
            this.prenom = prenom;
        }
        
        public String getEmail() {
            return email;
        }
        
        public void setEmail(String email) {
            this.email = email;
        }
        
        public String getUsername() {
            return username;
        }
        
        public void setUsername(String username) {
            this.username = username;
        }
    }
    
    public static class EntiteInfo implements Serializable {
        private Long id;
        private String nom;
        private String type;
        private String pays;
        private String ville;
        
        public String getDescription() {
            StringBuilder desc = new StringBuilder();
            if (nom != null) {
                desc.append(nom);
            }
            if (ville != null && pays != null) {
                desc.append(" (").append(ville).append(", ").append(pays).append(")");
            }
            return desc.toString();
        }
        
        // Getters et Setters
        public Long getId() {
            return id;
        }
        
        public void setId(Long id) {
            this.id = id;
        }
        
        public String getNom() {
            return nom;
        }
        
        public void setNom(String nom) {
            this.nom = nom;
        }
        
        public String getType() {
            return type;
        }
        
        public void setType(String type) {
            this.type = type;
        }
        
        public String getPays() {
            return pays;
        }
        
        public void setPays(String pays) {
            this.pays = pays;
        }
        
        public String getVille() {
            return ville;
        }
        
        public void setVille(String ville) {
            this.ville = ville;
        }
    }
}