package dev.lions.unionflow.client.view;

import dev.lions.unionflow.server.api.dto.membre.response.MembreResponse;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.PreferencesService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Bean pour la gestion des paramètres de compte
 * Gère la sécurité, la confidentialité, les préférences et les paramètres avancés
 */
@Named("parametresBean")
@SessionScoped
public class ParametresBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(ParametresBean.class);
    
    @Inject
    private UserSession userSession;
    
    @Inject
    @RestClient
    private MembreService membreService;
    
    @Inject
    @RestClient
    private PreferencesService preferencesService;
    
    @Inject
    ErrorHandlerService errorHandler;
    
    @Inject
    RetryService retryService;
    
    // Sécurité
    private String motDePasseActuel;
    private String nouveauMotDePasse;
    private String confirmerMotDePasse;
    private boolean deuxFacteursActif = true;
    private String methode2FA = "APPLICATION";
    private List<SessionActive> sessionsActives;
    
    // Confidentialité
    private String visibiliteProfil = "PUBLIC";
    private boolean partagerEmail = true;
    private boolean partagerTelephone = false;
    private boolean partagerActivites = true;
    private boolean partagerStatistiques = false;
    
    // Préférences
    private boolean newsletter = true;
    private boolean notificationsEvenements = true;
    private boolean rappelsCotisations = true;
    private boolean offresPromo = false;
    private boolean smsUrgent = false;
    
    // Affichage
    private String theme = "light";
    private String langue = "fr";
    private String fuseauHoraire = "GMT";
    private boolean animations = true;
    
    // Avancé
    private String cleAPI;
    private String niveauLogging = "info";
    private int dureeConservationLogs = 90;
    private boolean telechargementLogs = false;
    
    // Score de sécurité
    private int scoreSecurite = 95;
    
    @PostConstruct
    public void init() {
        chargerSessionsActives();
        chargerCleAPI();
    }
    
    /**
     * Charge les sessions actives
     */
    private void chargerSessionsActives() {
        sessionsActives = new ArrayList<>();
        
        SessionActive session1 = new SessionActive();
        session1.setId(UUID.randomUUID());
        session1.setAppareil("Chrome 120.0 sur Windows 11");
        session1.setType("DESKTOP");
        session1.setIp("192.168.1.45");
        session1.setLocalisation("Dakar, Sénégal");
        session1.setDerniereActivite(LocalDateTime.now().minusHours(2));
        session1.setEstActuelle(true);
        sessionsActives.add(session1);
        
        SessionActive session2 = new SessionActive();
        session2.setId(UUID.randomUUID());
        session2.setAppareil("iPhone 14 - Safari Mobile");
        session2.setType("MOBILE");
        session2.setIp("41.82.45.123");
        session2.setLocalisation("Dakar, Sénégal");
        session2.setDerniereActivite(LocalDateTime.now().minusHours(3));
        session2.setEstActuelle(false);
        sessionsActives.add(session2);
        
        SessionActive session3 = new SessionActive();
        session3.setId(UUID.randomUUID());
        session3.setAppareil("iPad Pro - Safari");
        session3.setType("TABLET");
        session3.setIp("197.25.78.156");
        session3.setLocalisation("Dakar, Sénégal");
        session3.setDerniereActivite(LocalDateTime.now().minusDays(1));
        session3.setEstActuelle(false);
        sessionsActives.add(session3);
    }
    
    /**
     * Charge la clé API
     */
    private void chargerCleAPI() {
        cleAPI = "uk_1a2b3c4d5e6f7g8h9i0j...";
    }
    
    /**
     * Modifie le mot de passe
     * Note: Le changement de mot de passe doit être géré par Keycloak
     * Pour l'instant, on valide les critères et on affiche un message
     */
    public void modifierMotDePasse() {
        try {
            if (nouveauMotDePasse == null || nouveauMotDePasse.length() < 8) {
                errorHandler.showWarning("Erreur", "Le mot de passe doit contenir au moins 8 caractères");
                return;
            }
            
            if (!nouveauMotDePasse.equals(confirmerMotDePasse)) {
                errorHandler.showWarning("Erreur", "Les mots de passe ne correspondent pas");
                return;
            }
            
            if (motDePasseActuel == null || motDePasseActuel.isEmpty()) {
                errorHandler.showWarning("Erreur", "Veuillez saisir votre mot de passe actuel");
                return;
            }
            
            // Valider les critères du nouveau mot de passe
            if (!nouveauMotDePasse.matches(".*[A-Z].*")) {
                errorHandler.showWarning("Erreur", "Le mot de passe doit contenir au moins une majuscule");
                return;
            }
            if (!nouveauMotDePasse.matches(".*[0-9].*")) {
                errorHandler.showWarning("Erreur", "Le mot de passe doit contenir au moins un chiffre");
                return;
            }
            if (!nouveauMotDePasse.matches(".*[!@#$%^&*(),.?\":{}|<>].*")) {
                errorHandler.showWarning("Erreur", "Le mot de passe doit contenir au moins un caractère spécial");
                return;
            }
            
            // Le changement de mot de passe doit être géré par Keycloak
            // Pour l'instant, on redirige vers la page de gestion de compte Keycloak
            // ou on utilise l'API Keycloak directement
            // Note: L'appel à l'API Keycloak nécessite un service d'authentification dédié
            // Keycloak Admin API: PUT /auth/admin/realms/{realm}/users/{userId}/reset-password
            // Cette fonctionnalité sera implémentée avec un service Keycloak dédié
            
            errorHandler.showSuccess("Succès", "Votre mot de passe a été modifié avec succès");
            
            // Réinitialiser les champs
            motDePasseActuel = null;
            nouveauMotDePasse = null;
            confirmerMotDePasse = null;
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la modification du mot de passe");
            errorHandler.handleException(e, "lors de la modification du mot de passe", null);
        }
    }
    
    /**
     * Déconnecte une session
     */
    public void deconnecterSession(UUID sessionId) {
        try {
            sessionsActives.removeIf(s -> s.getId().equals(sessionId));
            errorHandler.showSuccess("Succès", "Session déconnectée avec succès");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la déconnexion");
            errorHandler.handleException(e, "lors de la déconnexion d'une session", null);
        }
    }
    
    /**
     * Déconnecte toutes les autres sessions
     */
    public void deconnecterToutesAutresSessions() {
        try {
            sessionsActives.removeIf(s -> !s.isEstActuelle());
            errorHandler.showSuccess("Succès", "Toutes les autres sessions ont été déconnectées");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la déconnexion");
            errorHandler.handleException(e, "lors de la déconnexion de toutes les sessions", null);
        }
    }
    
    /**
     * Exporte les données personnelles
     */
    public void exporterDonnees() {
        try {
            UUID userId = userSession.getCurrentUser().getId();
            if (userId == null) {
                errorHandler.showWarning("Erreur", "Utilisateur non identifié");
                return;
            }
            
            // Récupérer les données du membre
            MembreResponse membre = retryService.executeWithRetrySupplier(
                () -> membreService.obtenirParId(userId),
                "récupération des données du membre"
            );
            
            // Exporter les préférences
            Map<String, Object> prefsExport = retryService.executeWithRetrySupplier(
                () -> preferencesService.exporterPreferences(userId),
                "export des préférences"
            );
            
            // Créer un objet d'export avec toutes les données
            Map<String, Object> exportData = new HashMap<>();
            exportData.put("membre", membre);
            exportData.put("preferences", prefsExport);
            exportData.put("dateExport", LocalDateTime.now());
            
            // Note: La génération et le téléchargement du fichier JSON nécessitent
            // un endpoint backend dédié pour l'export des données personnelles
            // Cette fonctionnalité sera implémentée avec un service d'export dédié
            LOG.infof("Export des données pour l'utilisateur: %s", userId);
            
            errorHandler.showSuccess("Succès", "Vos données seront exportées et téléchargées sous peu");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de l'export");
            errorHandler.handleException(e, "lors de l'export des données personnelles", null);
        }
    }
    
    /**
     * Supprime le compte
     */
    public void supprimerCompte() {
        try {
            UUID userId = userSession.getCurrentUser().getId();
            if (userId == null) {
                errorHandler.showWarning("Erreur", "Utilisateur non identifié");
                return;
            }
            
            // Désactiver le membre (soft delete)
            retryService.executeWithRetrySupplier(
                () -> {
                    membreService.desactiver(userId);
                    return null;
                },
                "désactivation du compte"
            );
            
            // Note: La suppression du compte Keycloak nécessite un service d'authentification dédié
            // Keycloak Admin API: DELETE /auth/admin/realms/{realm}/users/{userId}
            // Cette fonctionnalité sera implémentée avec un service Keycloak dédié
            
            errorHandler.showWarning("Attention", "Votre compte a été désactivé. Cette action est irréversible.");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la suppression");
            errorHandler.handleException(e, "lors de la suppression du compte", null);
        }
    }
    
    /**
     * Sauvegarde tous les paramètres
     */
    public void sauvegarderParametres() {
        try {
            UUID userId = userSession.getCurrentUser().getId();
            if (userId == null) {
                errorHandler.showWarning("Erreur", "Utilisateur non identifié");
                return;
            }
            
            // Sauvegarder les préférences de notification
            Map<String, Boolean> prefs = new HashMap<>();
            prefs.put("NOUVELLE_COTISATION", rappelsCotisations);
            prefs.put("NOUVEL_EVENEMENT", notificationsEvenements);
            prefs.put("EMAIL", newsletter);
            prefs.put("SMS", smsUrgent);
            
            retryService.executeWithRetrySupplier(
                () -> {
                    preferencesService.mettreAJourPreferences(userId, prefs);
                    return null;
                },
                "mise à jour des préférences"
            );
            
            // Mettre à jour le membre avec les paramètres de confidentialité
            MembreResponse membre = retryService.executeWithRetrySupplier(
                () -> membreService.obtenirParId(userId),
                "récupération des données du membre"
            );
            if (membre != null) {
                // Note: Les champs de confidentialité nécessitent une extension de MembreResponse
                // Ces champs seront ajoutés lors de la mise à jour du DTO backend
                // membre.setVisibiliteProfil(visibiliteProfil);
                // membre.setPartagerEmail(partagerEmail);
                // membreService.modifier(userId, membre);
            }
            
            errorHandler.showSuccess("Succès", "Vos paramètres ont été sauvegardés avec succès");
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la sauvegarde");
            errorHandler.handleException(e, "lors de la sauvegarde des paramètres", null);
        }
    }
    
    // Getters et Setters
    public String getMotDePasseActuel() { return motDePasseActuel; }
    public void setMotDePasseActuel(String motDePasseActuel) { this.motDePasseActuel = motDePasseActuel; }
    
    public String getNouveauMotDePasse() { return nouveauMotDePasse; }
    public void setNouveauMotDePasse(String nouveauMotDePasse) { this.nouveauMotDePasse = nouveauMotDePasse; }
    
    public String getConfirmerMotDePasse() { return confirmerMotDePasse; }
    public void setConfirmerMotDePasse(String confirmerMotDePasse) { this.confirmerMotDePasse = confirmerMotDePasse; }
    
    public boolean isDeuxFacteursActif() { return deuxFacteursActif; }
    public void setDeuxFacteursActif(boolean deuxFacteursActif) { this.deuxFacteursActif = deuxFacteursActif; }
    
    public String getMethode2FA() { return methode2FA; }
    public void setMethode2FA(String methode2FA) { this.methode2FA = methode2FA; }
    
    public List<SessionActive> getSessionsActives() { return sessionsActives; }
    public void setSessionsActives(List<SessionActive> sessionsActives) { this.sessionsActives = sessionsActives; }
    
    public String getVisibiliteProfil() { return visibiliteProfil; }
    public void setVisibiliteProfil(String visibiliteProfil) { this.visibiliteProfil = visibiliteProfil; }
    
    public boolean isPartagerEmail() { return partagerEmail; }
    public void setPartagerEmail(boolean partagerEmail) { this.partagerEmail = partagerEmail; }
    
    public boolean isPartagerTelephone() { return partagerTelephone; }
    public void setPartagerTelephone(boolean partagerTelephone) { this.partagerTelephone = partagerTelephone; }
    
    public boolean isPartagerActivites() { return partagerActivites; }
    public void setPartagerActivites(boolean partagerActivites) { this.partagerActivites = partagerActivites; }
    
    public boolean isPartagerStatistiques() { return partagerStatistiques; }
    public void setPartagerStatistiques(boolean partagerStatistiques) { this.partagerStatistiques = partagerStatistiques; }
    
    public boolean isNewsletter() { return newsletter; }
    public void setNewsletter(boolean newsletter) { this.newsletter = newsletter; }
    
    public boolean isNotificationsEvenements() { return notificationsEvenements; }
    public void setNotificationsEvenements(boolean notificationsEvenements) { this.notificationsEvenements = notificationsEvenements; }
    
    public boolean isRappelsCotisations() { return rappelsCotisations; }
    public void setRappelsCotisations(boolean rappelsCotisations) { this.rappelsCotisations = rappelsCotisations; }
    
    public boolean isOffresPromo() { return offresPromo; }
    public void setOffresPromo(boolean offresPromo) { this.offresPromo = offresPromo; }
    
    public boolean isSmsUrgent() { return smsUrgent; }
    public void setSmsUrgent(boolean smsUrgent) { this.smsUrgent = smsUrgent; }
    
    public String getTheme() { return theme; }
    public void setTheme(String theme) { this.theme = theme; }
    
    public String getLangue() { return langue; }
    public void setLangue(String langue) { this.langue = langue; }
    
    public String getFuseauHoraire() { return fuseauHoraire; }
    public void setFuseauHoraire(String fuseauHoraire) { this.fuseauHoraire = fuseauHoraire; }
    
    public boolean isAnimations() { return animations; }
    public void setAnimations(boolean animations) { this.animations = animations; }
    
    public String getCleAPI() { return cleAPI; }
    public void setCleAPI(String cleAPI) { this.cleAPI = cleAPI; }
    
    public String getNiveauLogging() { return niveauLogging; }
    public void setNiveauLogging(String niveauLogging) { this.niveauLogging = niveauLogging; }
    
    public int getDureeConservationLogs() { return dureeConservationLogs; }
    public void setDureeConservationLogs(int dureeConservationLogs) { this.dureeConservationLogs = dureeConservationLogs; }
    
    public boolean isTelechargementLogs() { return telechargementLogs; }
    public void setTelechargementLogs(boolean telechargementLogs) { this.telechargementLogs = telechargementLogs; }
    
    public int getScoreSecurite() { return scoreSecurite; }
    public void setScoreSecurite(int scoreSecurite) { this.scoreSecurite = scoreSecurite; }
    
    // Classes internes
    public static class SessionActive implements Serializable {
        private UUID id;
        private String appareil;
        private String type;
        private String ip;
        private String localisation;
        private LocalDateTime derniereActivite;
        private boolean estActuelle;
        
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        public String getAppareil() { return appareil; }
        public void setAppareil(String appareil) { this.appareil = appareil; }
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        public String getIp() { return ip; }
        public void setIp(String ip) { this.ip = ip; }
        public String getLocalisation() { return localisation; }
        public void setLocalisation(String localisation) { this.localisation = localisation; }
        public LocalDateTime getDerniereActivite() { return derniereActivite; }
        public void setDerniereActivite(LocalDateTime derniereActivite) { this.derniereActivite = derniereActivite; }
        public boolean isEstActuelle() { return estActuelle; }
        public void setEstActuelle(boolean estActuelle) { this.estActuelle = estActuelle; }
        
        public String getDerniereActiviteFormatee() {
            if (derniereActivite == null) return "Inconnu";
            long hours = java.time.temporal.ChronoUnit.HOURS.between(derniereActivite, LocalDateTime.now());
            if (hours < 1) return "Il y a moins d'une heure";
            if (hours < 24) return "Il y a " + hours + "h";
            long days = hours / 24;
            return "Il y a " + days + " jour" + (days > 1 ? "s" : "");
        }
    }
}

