package dev.lions.unionflow.client.view;

import dev.lions.unionflow.server.api.dto.role.response.RoleResponse;
import dev.lions.unionflow.client.service.AdminUserService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Named("rolesBean")
@SessionScoped
public class RolesBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Inject
    @RestClient
    private AdminUserService adminUserService;
    
    // Filtres
    private String filtreNom = "";
    private String filtreType = "";
    private String filtreStatut = "";
    
    // Rôles
    private List<Role> roles;
    private Role roleSelectionne;
    private Role nouveauRole = new Role();
    /** Rôle en attente de confirmation de suppression (flux explicite). */
    private Role rolePourSuppression;
    
    @jakarta.annotation.PostConstruct
    public void init() {
        initialiserRoles();
    }
    
    private void initialiserRoles() {
        roles = new ArrayList<>();
        try {
            List<RoleResponse> dtos = adminUserService.getRealmRoles();
            if (dtos != null) {
                for (RoleResponse dto : dtos) {
                    Role r = new Role();
                    // Corrigé: RoleResponse a getCode() et getLibelle(), pas getName()
                    r.setCode(dto.getCode() != null ? dto.getCode() : (dto.getId() != null ? dto.getId().toString() : ""));
                    r.setNom(dto.getLibelle());
                    r.setDescription(dto.getDescription());
                    r.setType(TypeRole.SYSTEME);
                    r.setStatut(StatutRole.ACTIF);
                    r.setNombreUtilisateurs(0);
                    r.setDateModification(LocalDateTime.now());
                    r.setModifiePar("Système");
                    r.setPermissions(new ArrayList<>());
                    roles.add(r);
                }
            }
        } catch (Exception e) {
            // API admin réservée SUPER_ADMIN ; liste vide si non autorisé
        }
    }
    
    // Getters pour les KPIs
    public int getTotalRoles() {
        return roles.size();
    }
    
    public int getRolesActifs() {
        return (int) roles.stream().filter(r -> r.getStatut() == StatutRole.ACTIF).count();
    }
    
    public int getUtilisateursAvecRoles() {
        return roles.stream().mapToInt(Role::getNombreUtilisateurs).sum();
    }
    
    public int getPermissionsUniques() {
        return roles.stream()
                   .flatMap(r -> r.getPermissions().stream())
                   .collect(Collectors.toSet())
                   .size();
    }
    
    // Filtrage des rôles
    public List<Role> getRolesFiltres() {
        return roles.stream()
                   .filter(this::correspondAuxFiltres)
                   .collect(Collectors.toList());
    }
    
    private boolean correspondAuxFiltres(Role role) {
        boolean nomOk = filtreNom.isEmpty() || 
                       role.getNom().toLowerCase().contains(filtreNom.toLowerCase()) ||
                       role.getDescription().toLowerCase().contains(filtreNom.toLowerCase());
        
        boolean typeOk = filtreType.isEmpty() || role.getType().name().equals(filtreType);
        boolean statutOk = filtreStatut.isEmpty() || role.getStatut().name().equals(filtreStatut);
        
        return nomOk && typeOk && statutOk;
    }
    
    public void reinitialiserFiltres() {
        filtreNom = "";
        filtreType = "";
        filtreStatut = "";
    }
    
    // Actions
    public void voirRole(Role role) {
        this.roleSelectionne = role;
        // Charger les détails complets du rôle
        role.chargerDetailsComplets();
    }
    
    public void modifierRole(Role role) {
        this.roleSelectionne = role;
    }
    
    public void gererUtilisateurs(Role role) {
        this.roleSelectionne = role;
    }

    /**
     * Prépare la suppression (ouvre le dialogue de confirmation).
     */
    public void preparerSuppression(Role role) {
        this.rolePourSuppression = role;
    }

    /**
     * Confirme et exécute la suppression après clic sur « Oui » dans le dialogue.
     */
    public void confirmerSuppression() {
        if (rolePourSuppression == null) return;
        Role r = rolePourSuppression;
        rolePourSuppression = null;
        supprimerRole(r);
    }

    /**
     * Supprime un rôle de la liste (côté client ; pas d'API delete dans AdminUserService).
     */
    public void supprimerRole(Role role) {
        if (role != null && roles != null) {
            roles.remove(role);
        }
    }
    
    public void creerRole() {
        // Validation
        if (nouveauRole.getNom().isEmpty()) {
            return;
        }
        
        // Génération des propriétés
        nouveauRole.setCode(genererCodeRole(nouveauRole.getNom()));
        nouveauRole.setCouleurFond(genererCouleurAleatoire());
        nouveauRole.setCouleurTexte("#ffffff");
        nouveauRole.setStatut(StatutRole.ACTIF);
        nouveauRole.setDateModification(LocalDateTime.now());
        nouveauRole.setModifiePar("Utilisateur Courant");
        
        // Ajout à la liste
        roles.add(nouveauRole);
        
        // Réinitialisation
        nouveauRole = new Role();
    }
    
    private String genererCodeRole(String nom) {
        return nom.toUpperCase()
                 .replaceAll("[^A-Z0-9]", "_")
                 .replaceAll("_{2,}", "_");
    }
    
    private String genererCouleurAleatoire() {
        String[] couleurs = {"#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#feca57", 
                           "#a55eea", "#fd79a8", "#6c5ce7", "#74b9ff", "#00b894"};
        Random random = new Random();
        return couleurs[random.nextInt(couleurs.length)];
    }
    
    public List<Permission> getPermissionsDisponibles() {
        List<Permission> permissions = new ArrayList<>();
        permissions.add(new Permission("GESTION_COMPLETE", "Gestion Complète"));
        permissions.add(new Permission("ADMIN_SYSTEME", "Administration Système"));
        permissions.add(new Permission("GESTION_USERS", "Gestion des Utilisateurs"));
        permissions.add(new Permission("GESTION_ORGS", "Gestion des Organisations"));
        permissions.add(new Permission("GESTION_MEMBRES", "Gestion des Membres"));
        permissions.add(new Permission("GESTION_EVENTS", "Gestion des Événements"));
        permissions.add(new Permission("COMPTABILITE", "Comptabilité"));
        permissions.add(new Permission("COTISATIONS", "Cotisations"));
        permissions.add(new Permission("DOCUMENTS", "Documents"));
        permissions.add(new Permission("COMMUNICATIONS", "Communications"));
        permissions.add(new Permission("RAPPORTS", "Rapports"));
        permissions.add(new Permission("AUDIT", "Audit"));
        permissions.add(new Permission("CONSULTATION", "Consultation"));
        return permissions;
    }
    
    // Getters et Setters
    public String getFiltreNom() { return filtreNom; }
    public void setFiltreNom(String filtreNom) { this.filtreNom = filtreNom; }
    
    public String getFiltreType() { return filtreType; }
    public void setFiltreType(String filtreType) { this.filtreType = filtreType; }
    
    public String getFiltreStatut() { return filtreStatut; }
    public void setFiltreStatut(String filtreStatut) { this.filtreStatut = filtreStatut; }
    
    public Role getRoleSelectionne() { return roleSelectionne; }
    public void setRoleSelectionne(Role roleSelectionne) { this.roleSelectionne = roleSelectionne; }
    
    public Role getNouveauRole() { return nouveauRole; }
    public void setNouveauRole(Role nouveauRole) { this.nouveauRole = nouveauRole; }
    
    // Classes internes
    public static class Role implements Serializable {
        private String code;
        private String nom;
        private String description;
        private TypeRole type;
        private StatutRole statut;
        private String icone;
        private String couleurFond;
        private String couleurTexte;
        private List<String> permissions;
        private int nombreUtilisateurs;
        private LocalDateTime dateModification;
        private String modifiePar;
        
        // Détails complets (chargés à la demande)
        private List<Permission> permissionsDetaillees;
        private List<Utilisateur> utilisateursAssignes;
        
        public Role() {
            this.permissions = new ArrayList<>();
        }
        
        public Role(String code, String nom, String description, TypeRole type, StatutRole statut,
                   String icone, String couleurFond, String couleurTexte, List<String> permissions,
                   int nombreUtilisateurs, LocalDateTime dateModification, String modifiePar) {
            this.code = code;
            this.nom = nom;
            this.description = description;
            this.type = type;
            this.statut = statut;
            this.icone = icone;
            this.couleurFond = couleurFond;
            this.couleurTexte = couleurTexte;
            this.permissions = permissions != null ? permissions : new ArrayList<>();
            this.nombreUtilisateurs = nombreUtilisateurs;
            this.dateModification = dateModification;
            this.modifiePar = modifiePar;
        }
        
        public void chargerDetailsComplets() {
            // Simuler le chargement des détails
            permissionsDetaillees = new ArrayList<>();
            for (String perm : permissions) {
                permissionsDetaillees.add(new Permission(perm, getLibellePermission(perm)));
            }
            
            utilisateursAssignes = new ArrayList<>();
            for (int i = 0; i < Math.min(nombreUtilisateurs, 10); i++) {
                utilisateursAssignes.add(new Utilisateur("Utilisateur " + (i+1), "Test"));
            }
        }
        
        private String getLibellePermission(String code) {
            Map<String, String> libelles = new HashMap<>();
            libelles.put("GESTION_COMPLETE", "Gestion Complète");
            libelles.put("ADMIN_SYSTEME", "Administration Système");
            libelles.put("GESTION_USERS", "Gestion des Utilisateurs");
            libelles.put("GESTION_ORGS", "Gestion des Organisations");
            libelles.put("GESTION_MEMBRES", "Gestion des Membres");
            libelles.put("GESTION_EVENTS", "Gestion des Événements");
            libelles.put("COMPTABILITE", "Comptabilité");
            libelles.put("COTISATIONS", "Cotisations");
            libelles.put("DOCUMENTS", "Documents");
            libelles.put("COMMUNICATIONS", "Communications");
            libelles.put("RAPPORTS", "Rapports");
            libelles.put("AUDIT", "Audit");
            libelles.put("CONSULTATION", "Consultation");
            return libelles.getOrDefault(code, code);
        }
        
        // Propriétés calculées
        public String getTypeLibelle() {
            switch (type) {
                case SYSTEME: return "Système";
                case PERSONNALISE: return "Personnalisé";
                case TEMPORAIRE: return "Temporaire";
                default: return type.name();
            }
        }
        
        public String getTypeSeverity() {
            switch (type) {
                case SYSTEME: return "danger";
                case PERSONNALISE: return "info";
                case TEMPORAIRE: return "warning";
                default: return "secondary";
            }
        }
        
        public String getStatutLibelle() {
            switch (statut) {
                case ACTIF: return "Actif";
                case INACTIF: return "Inactif";
                case SUSPENDU: return "Suspendu";
                default: return statut.name();
            }
        }
        
        public String getStatutSeverity() {
            switch (statut) {
                case ACTIF: return "success";
                case INACTIF: return "secondary";
                case SUSPENDU: return "warning";
                default: return "secondary";
            }
        }
        
        public List<String> getPermissionsPrincipales() {
            return permissions.stream().limit(3).collect(Collectors.toList());
        }
        
        public int getPermissionsCount() {
            return permissions.size();
        }
        
        public String getDateModificationFormatee() {
            return dateModification.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
        }
        
        public boolean isModifiable() {
            return type != TypeRole.SYSTEME;
        }
        
        public boolean isSupprimable() {
            return type != TypeRole.SYSTEME && nombreUtilisateurs == 0;
        }
        
        // Getters et Setters
        public String getCode() { return code; }
        public void setCode(String code) { this.code = code; }
        
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public TypeRole getType() { return type; }
        public void setType(TypeRole type) { this.type = type; }
        
        public StatutRole getStatut() { return statut; }
        public void setStatut(StatutRole statut) { this.statut = statut; }
        
        public String getIcone() { return icone; }
        public void setIcone(String icone) { this.icone = icone; }
        
        public String getCouleurFond() { return couleurFond; }
        public void setCouleurFond(String couleurFond) { this.couleurFond = couleurFond; }
        
        public String getCouleurTexte() { return couleurTexte; }
        public void setCouleurTexte(String couleurTexte) { this.couleurTexte = couleurTexte; }
        
        public List<String> getPermissions() { return permissions; }
        public void setPermissions(List<String> permissions) { this.permissions = permissions; }
        
        public int getNombreUtilisateurs() { return nombreUtilisateurs; }
        public void setNombreUtilisateurs(int nombreUtilisateurs) { this.nombreUtilisateurs = nombreUtilisateurs; }
        
        public LocalDateTime getDateModification() { return dateModification; }
        public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
        
        public String getModifiePar() { return modifiePar; }
        public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
        
        public List<Permission> getPermissionsDetaillees() { return permissionsDetaillees; }
        public List<Utilisateur> getUtilisateursAssignes() { return utilisateursAssignes; }
    }
    
    public enum TypeRole {
        SYSTEME, PERSONNALISE, TEMPORAIRE
    }
    
    public enum StatutRole {
        ACTIF, INACTIF, SUSPENDU
    }
    
    public static class Permission implements Serializable {
        private String code;
        private String libelle;
        
        public Permission(String code, String libelle) {
            this.code = code;
            this.libelle = libelle;
        }
        
        public String getCode() { return code; }
        public String getLibelle() { return libelle; }
    }
    
    public static class Utilisateur implements Serializable {
        private String nom;
        private String prenom;
        
        public Utilisateur(String nom, String prenom) {
            this.nom = nom;
            this.prenom = prenom;
        }
        
        public String getNom() { return nom; }
        public String getPrenom() { return prenom; }
    }
}
