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

import dev.lions.user.manager.client.service.AuditServiceClient;
import dev.lions.user.manager.client.service.RoleServiceClient;
import dev.lions.user.manager.client.service.UserMetricsServiceClient;
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.config.inject.ConfigProperty;
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.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 UserMetricsServiceClient userMetricsServiceClient;

    @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager")
    String defaultRealm;

    // Statistiques
    private Long totalUsers = 0L;
    private Long totalRoles = 0L;
    private Long recentActions = 0L;
    private Long activeSessions = 0L;
    private Long onlineUsers = 0L;

    // Indicateur de chargement
    private boolean loading = false;

    // Méthodes pour obtenir les valeurs formatées pour l'affichage
    public String getTotalUsersDisplay() {
        if (loading)
            return "...";
        return totalUsers != null ? String.valueOf(totalUsers) : "0";
    }

    public String getTotalRolesDisplay() {
        if (loading)
            return "...";
        return totalRoles != null ? String.valueOf(totalRoles) : "0";
    }

    public String getRecentActionsDisplay() {
        if (loading)
            return "...";
        return recentActions != null ? String.valueOf(recentActions) : "0";
    }

    public String getActiveSessionsDisplay() {
        if (loading)
            return "...";
        return activeSessions != null ? String.valueOf(activeSessions) : "0";
    }

    public String getOnlineUsersDisplay() {
        if (loading)
            return "...";
        return onlineUsers != null ? String.valueOf(onlineUsers) : "0";
    }

    public boolean isLoading() {
        return loading;
    }

    // Realm par défaut (initialisé depuis la config en @PostConstruct)
    private String realmName;

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

    @PostConstruct
    public void init() {
        this.realmName = defaultRealm;
        LOGGER.info("Initialisation DashboardBean pour realm: " + realmName);
        loadStatistics();
    }

    /**
     * Charger toutes les statistiques
     */
    public void loadStatistics() {
        loading = true;
        try {
            loadTotalUsers();
            loadTotalRoles();
            loadRecentActions();
            loadSessionStats();
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
        } finally {
            loading = false;
        }
    }

    /**
     * Charger le nombre total d'utilisateurs
     */
    private void loadTotalUsers() {
        try {
            UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                    .realmName(realmName)
                    .page(0)
                    .pageSize(1)
                    .build();

            UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
            totalUsers = (result != null && result.getTotalCount() != null) ? result.getTotalCount() : 0L;
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement total utilisateurs: " + e.getMessage());
            totalUsers = 0L;
            addErrorMessage("Impossible de charger le nombre d'utilisateurs: " + e.getMessage());
        }
    }

    /**
     * Charger le nombre total de rôles Realm
     */
    private void loadTotalRoles() {
        try {
            List<?> roles = roleServiceClient.getAllRealmRoles(realmName);
            totalRoles = (roles != null) ? (long) roles.size() : 0L;
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement total rôles: " + e.getMessage());
            totalRoles = 0L;
            addErrorMessage("Impossible de charger le nombre de rôles: " + e.getMessage());
        }
    }

    /**
     * Charger le nombre d'actions récentes (dernières 24h)
     */
    private void loadRecentActions() {
        try {
            String dateDebutStr = LocalDateTime.now().minusDays(1).format(DATE_FORMATTER);
            String dateFinStr = LocalDateTime.now().format(DATE_FORMATTER);

            try {
                dev.lions.user.manager.dto.common.CountDTO successDto = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr);
                dev.lions.user.manager.dto.common.CountDTO failureDto = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr);

                long successCount = (successDto != null) ? successDto.getCount() : 0L;
                long failureCount = (failureDto != null) ? failureDto.getCount() : 0L;
                recentActions = successCount + failureCount;
            } catch (Exception e2) {
                LOGGER.warning("Fallback searchLogs pour actions récentes: " + e2.getMessage());
                List<?> logs = auditServiceClient.searchLogs(null, dateDebutStr, dateFinStr, null, null, null, 0, 100);
                recentActions = (logs != null) ? (long) logs.size() : 0L;
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement actions récentes: " + e.getMessage());
            recentActions = 0L;
        }
    }

    /**
     * Charger les statistiques de sessions / utilisateurs en ligne
     */
    private void loadSessionStats() {
        try {
            dev.lions.user.manager.dto.common.UserSessionStatsDTO stats = userMetricsServiceClient
                    .getUserSessionStats(realmName);

            if (stats != null) {
                this.activeSessions = stats.getActiveSessions();
                this.onlineUsers = stats.getOnlineUsers();
            } else {
                this.activeSessions = 0L;
                this.onlineUsers = 0L;
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur chargement stats sessions: " + e.getMessage());
            this.activeSessions = 0L;
            this.onlineUsers = 0L;
        }
    }

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

    // 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));
    }
}
