package dev.lions.user.manager.client.view;

import dev.lions.user.manager.client.service.AuditServiceClient;
import dev.lions.user.manager.client.service.RealmServiceClient;
import dev.lions.user.manager.client.service.RoleServiceClient;
import dev.lions.user.manager.client.service.UserServiceClient;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import lombok.Data;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

/**
 * Bean JSF pour le tableau de bord
 * 
 * @author Lions User Manager
 * @version 1.0.0
 */
@Named("dashboardBean")
@ViewScoped
@Data
public class DashboardBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = Logger.getLogger(DashboardBean.class.getName());

    @Inject
    @RestClient
    private UserServiceClient userServiceClient;

    @Inject
    @RestClient
    private RoleServiceClient roleServiceClient;

    @Inject
    @RestClient
    private AuditServiceClient auditServiceClient;

    @Inject
    @RestClient
    private RealmServiceClient realmServiceClient;

    @Inject
    private UserSessionBean userSessionBean;

    // ==================== STATISTIQUES MÉTIER ====================

    // Utilisateurs
    private Long totalUsers = 0L;
    private Long activeUsers = 0L;  // enabled=true
    private Long inactiveUsers = 0L;  // enabled=false
    private Long usersCreatedToday = 0L;
    private Long usersCreatedThisWeek = 0L;
    private Long usersCreatedThisMonth = 0L;

    // Rôles
    private Long totalRoles = 0L;

    // Audit & Activité
    private Long actionsLast24h = 0L;
    private Long actionsLast7d = 0L;
    private Long actionsLast30d = 0L;
    private Long successfulActions24h = 0L;
    private Long failedActions24h = 0L;
    private Double successRate24h = 0.0;

    // Sécurité & Alertes
    private Long criticalActions24h = 0L;
    private Long failedLogins24h = 0L;
    private Long usersAtRisk = 0L; // Utilisateurs avec multiples tentatives échouées

    // Indicateur de chargement
    private boolean loading = false;
    
    // ==================== MÉTHODES D'AFFICHAGE ====================

    public String getTotalUsersDisplay() {
        return loading ? "..." : String.valueOf(totalUsers);
    }

    public String getActiveUsersDisplay() {
        return loading ? "..." : String.valueOf(activeUsers);
    }

    public String getInactiveUsersDisplay() {
        return loading ? "..." : String.valueOf(inactiveUsers);
    }

    public String getUsersCreatedTodayDisplay() {
        return loading ? "..." : String.valueOf(usersCreatedToday);
    }

    public String getUsersCreatedThisWeekDisplay() {
        return loading ? "..." : String.valueOf(usersCreatedThisWeek);
    }

    public String getTotalRolesDisplay() {
        return loading ? "..." : String.valueOf(totalRoles);
    }

    public String getActionsLast24hDisplay() {
        return loading ? "..." : String.valueOf(actionsLast24h);
    }

    public String getActionsLast7dDisplay() {
        return loading ? "..." : String.valueOf(actionsLast7d);
    }

    public String getSuccessRate24hDisplay() {
        return loading ? "..." : String.format("%.1f%%", successRate24h);
    }

    public String getCriticalActions24hDisplay() {
        return loading ? "..." : String.valueOf(criticalActions24h);
    }

    public String getFailedLogins24hDisplay() {
        return loading ? "..." : String.valueOf(failedLogins24h);
    }

    public String getUsersAtRiskDisplay() {
        return loading ? "..." : String.valueOf(usersAtRisk);
    }

    public boolean isLoading() {
        return loading;
    }

    public boolean hasAlerts() {
        return criticalActions24h > 0 || failedLogins24h > 5 || usersAtRisk > 0;
    }

    // Realm - sera défini dynamiquement en fonction de l'utilisateur connecté
    private String realmName = "lions-user-manager";  // Valeur par défaut si aucun realm autorisé
    private List<String> availableRealms = new ArrayList<>();

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

    @PostConstruct
    public void init() {
        LOGGER.info("=== Initialisation du DashboardBean ===");
        LOGGER.info("UserServiceClient injecté: " + (userServiceClient != null ? "OUI" : "NON"));
        LOGGER.info("RoleServiceClient injecté: " + (roleServiceClient != null ? "OUI" : "NON"));
        LOGGER.info("AuditServiceClient injecté: " + (auditServiceClient != null ? "OUI" : "NON"));
        LOGGER.info("RealmServiceClient injecté: " + (realmServiceClient != null ? "OUI" : "NON"));
        LOGGER.info("UserSessionBean injecté: " + (userSessionBean != null ? "OUI" : "NON"));

        // Charger les realms autorisés pour l'utilisateur connecté (multi-tenant)
        loadRealms();

        LOGGER.info("Realm sélectionné pour le dashboard: " + realmName);

        // Charger les statistiques pour le realm de l'utilisateur
        loadStatistics();
    }

    /**
     * Charger toutes les statistiques métier
     */
    public void loadStatistics() {
        loading = true;
        try {
            // Statistiques utilisateurs
            loadUserStatistics();

            // Statistiques rôles
            loadTotalRoles();

            // Statistiques activité & audit
            loadActivityStatistics();

            // Statistiques sécurité
            loadSecurityStatistics();

        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
            e.printStackTrace();
        } finally {
            loading = false;
        }
    }

    /**
     * Charger les statistiques utilisateurs
     */
    private void loadUserStatistics() {
        try {
            // Total utilisateurs
            UserSearchCriteriaDTO criteriaAll = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .page(0)
                .pageSize(1)
                .build();
            UserSearchResultDTO resultAll = userServiceClient.searchUsers(criteriaAll);
            totalUsers = resultAll != null && resultAll.getTotalCount() != null ? resultAll.getTotalCount() : 0L;

            // Utilisateurs actifs (enabled=true)
            UserSearchCriteriaDTO criteriaActive = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .statut(dev.lions.user.manager.enums.user.StatutUser.ACTIF)
                .page(0)
                .pageSize(1)
                .build();
            UserSearchResultDTO resultActive = userServiceClient.searchUsers(criteriaActive);
            activeUsers = resultActive != null && resultActive.getTotalCount() != null ? resultActive.getTotalCount() : 0L;

            // Utilisateurs inactifs
            inactiveUsers = totalUsers - activeUsers;

            LOGGER.info("✅ Statistiques utilisateurs: Total=" + totalUsers + ", Actifs=" + activeUsers + ", Inactifs=" + inactiveUsers);

        } catch (Exception e) {
            LOGGER.severe("❌ Erreur chargement statistiques utilisateurs: " + e.getMessage());
            totalUsers = 0L;
            activeUsers = 0L;
            inactiveUsers = 0L;
        }
    }

    /**
     * Charger les statistiques d'activité (audit)
     */
    private void loadActivityStatistics() {
        try {
            LocalDateTime now = LocalDateTime.now();

            // Actions dernières 24h
            String date24hAgo = now.minusDays(1).format(DATE_FORMATTER);
            String dateNow = now.format(DATE_FORMATTER);

            try {
                AuditServiceClient.CountResponse success24h = auditServiceClient.getSuccessCount(date24hAgo, dateNow);
                AuditServiceClient.CountResponse failure24h = auditServiceClient.getFailureCount(date24hAgo, dateNow);

                successfulActions24h = success24h != null ? success24h.count : 0L;
                failedActions24h = failure24h != null ? failure24h.count : 0L;
                actionsLast24h = successfulActions24h + failedActions24h;

                // Taux de réussite
                if (actionsLast24h > 0) {
                    successRate24h = (successfulActions24h * 100.0) / actionsLast24h;
                } else {
                    successRate24h = 100.0;
                }

                LOGGER.info("✅ Actions 24h: Total=" + actionsLast24h + ", Succès=" + successfulActions24h +
                    ", Échecs=" + failedActions24h + ", Taux=" + String.format("%.1f%%", successRate24h));

            } catch (Exception e) {
                LOGGER.warning("⚠️ Impossible d'obtenir les stats d'audit 24h: " + e.getMessage());
                actionsLast24h = 0L;
                successfulActions24h = 0L;
                failedActions24h = 0L;
                successRate24h = 100.0;
            }

            // Actions derniers 7 jours
            try {
                String date7dAgo = now.minusDays(7).format(DATE_FORMATTER);
                AuditServiceClient.CountResponse success7d = auditServiceClient.getSuccessCount(date7dAgo, dateNow);
                AuditServiceClient.CountResponse failure7d = auditServiceClient.getFailureCount(date7dAgo, dateNow);
                actionsLast7d = (success7d != null ? success7d.count : 0L) + (failure7d != null ? failure7d.count : 0L);
            } catch (Exception e) {
                actionsLast7d = 0L;
            }

            // Actions derniers 30 jours
            try {
                String date30dAgo = now.minusDays(30).format(DATE_FORMATTER);
                AuditServiceClient.CountResponse success30d = auditServiceClient.getSuccessCount(date30dAgo, dateNow);
                AuditServiceClient.CountResponse failure30d = auditServiceClient.getFailureCount(date30dAgo, dateNow);
                actionsLast30d = (success30d != null ? success30d.count : 0L) + (failure30d != null ? failure30d.count : 0L);
            } catch (Exception e) {
                actionsLast30d = 0L;
            }

        } catch (Exception e) {
            LOGGER.severe("❌ Erreur chargement statistiques d'activité: " + e.getMessage());
        }
    }

    /**
     * Charger les statistiques de sécurité
     */
    private void loadSecurityStatistics() {
        try {
            LocalDateTime now = LocalDateTime.now();
            String date24hAgo = now.minusDays(1).format(DATE_FORMATTER);
            String dateNow = now.format(DATE_FORMATTER);

            // Actions critiques (suppressions, désactivations, modifications de rôles)
            // TODO: Implémenter avec un filtre sur les types d'actions critiques
            criticalActions24h = 0L;

            // Tentatives de connexion échouées
            // TODO: Implémenter avec un filtre sur CONNEXION_ECHOUEE
            failedLogins24h = failedActions24h; // Approximation pour l'instant

            // Utilisateurs à risque (plus de 3 tentatives échouées)
            // TODO: Implémenter avec un groupe by userId sur les échecs
            usersAtRisk = failedLogins24h > 10 ? 1L : 0L; // Approximation

            LOGGER.info("✅ Stats sécurité: Critiques=" + criticalActions24h +
                ", Échecs login=" + failedLogins24h + ", Utilisateurs à risque=" + usersAtRisk);

        } catch (Exception e) {
            LOGGER.severe("❌ Erreur chargement statistiques sécurité: " + e.getMessage());
            criticalActions24h = 0L;
            failedLogins24h = 0L;
            usersAtRisk = 0L;
        }
    }

    /**
     * Charger le nombre total de rôles Realm
     */
    private void loadTotalRoles() {
        try {
            LOGGER.info("Début chargement total rôles pour realm: " + realmName);
            LOGGER.info("Appel roleServiceClient.getAllRealmRoles()...");
            List<?> roles = roleServiceClient.getAllRealmRoles(realmName);
            LOGGER.info("Résultat reçu: " + (roles != null ? "NON NULL, taille: " + roles.size() : "NULL"));

            if (roles != null) {
                totalRoles = (long) roles.size();
                LOGGER.info("✅ Total rôles chargé avec succès: " + totalRoles);
            } else {
                LOGGER.warning("⚠️ Liste de rôles null");
                totalRoles = 0L;
            }
        } catch (Exception e) {
            LOGGER.severe("❌ ERREUR lors du chargement du nombre de rôles: " + e.getMessage());
            LOGGER.severe("   Type d'erreur: " + e.getClass().getName());
            e.printStackTrace();
            totalRoles = 0L;
            addErrorMessage("Impossible de charger le nombre de rôles: " + e.getMessage());
        }
    }

    /**
     * Rafraîchir les statistiques
     */
    public void refreshStatistics() {
        LOGGER.info("=== Rafraîchissement des statistiques ===");
        loadStatistics();
        addSuccessMessage("Statistiques rafraîchies avec succès");
    }

    /**
     * Charger les realms disponibles depuis Keycloak en fonction des permissions de l'utilisateur
     * Architecture multi-tenant: le realm est déterminé dynamiquement selon l'utilisateur connecté
     */
    private void loadRealms() {
        try {
            // Récupérer tous les realms depuis Keycloak
            List<String> allRealms = realmServiceClient.getAllRealms();

            if (allRealms == null || allRealms.isEmpty()) {
                LOGGER.warning("Aucun realm trouvé dans Keycloak");
                availableRealms = Collections.emptyList();
                return;
            }

            List<String> authorizedRealms = userSessionBean.getAuthorizedRealms();

            // Si liste vide, l'utilisateur est super admin (peut gérer tous les realms)
            if (authorizedRealms.isEmpty()) {
                // Super admin - utiliser tous les realms disponibles depuis Keycloak
                availableRealms = new ArrayList<>(allRealms);
                LOGGER.info("Super admin détecté - " + availableRealms.size() + " realms disponibles depuis Keycloak");
            } else {
                // Realm admin - filtrer pour ne garder que les realms autorisés qui existent dans Keycloak
                availableRealms = new ArrayList<>();
                for (String authorizedRealm : authorizedRealms) {
                    if (allRealms.contains(authorizedRealm)) {
                        availableRealms.add(authorizedRealm);
                    }
                }
                LOGGER.info("Realms autorisés pour l'utilisateur: " + availableRealms.size());

                // Définir le premier realm autorisé comme realm par défaut
                if (!availableRealms.isEmpty() && !availableRealms.contains(realmName)) {
                    realmName = availableRealms.get(0);
                    LOGGER.info("Realm par défaut changé vers: " + realmName);
                }
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des realms depuis Keycloak: " + e.getMessage());
            LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e);
            // Fallback: garder le realm par défaut "lions-user-manager"
            availableRealms = Collections.emptyList();
        }
    }

    // Méthodes utilitaires pour les messages
    private void addSuccessMessage(String message) {
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message));
    }

    private void addErrorMessage(String message) {
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message));
    }
}

