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.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
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 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.Map;
import java.util.logging.Logger;

/**
 * Bean JSF pour la consultation des logs d'audit
 * 
 * @author Lions User Manager
 * @version 1.0.0
 */
@Named("auditConsultationBean")
@ViewScoped
@Data
public class AuditConsultationBean implements Serializable {

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

    @Inject
    @RestClient
    private AuditServiceClient auditServiceClient;

    @Inject
    @RestClient
    private RealmServiceClient realmServiceClient;

    // Liste des logs
    private List<AuditLogDTO> auditLogs = new ArrayList<>();
    private AuditLogDTO selectedLog;

    // Filtres de recherche
    private String acteurUsername;
    private LocalDateTime dateDebut;
    private LocalDateTime dateFin;
    private TypeActionAudit selectedTypeAction;
    private String ressourceType;
    private Boolean succes;

    // Pagination
    private int currentPage = 0;
    private int pageSize = 50;
    private long totalRecords = 0;

    // Statistiques
    private Map<TypeActionAudit, Long> actionStatistics;
    private Map<String, Long> userActivityStatistics;
    private Long failureCount = 0L;
    private Long successCount = 0L;

    // Options
    private List<TypeActionAudit> typeActionOptions = List.of(TypeActionAudit.values());
    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() {
        loadRealms();
        loadStatistics();
    }

    /**
     * Rechercher des logs d'audit
     */
    public void searchLogs() {
        try {
            String dateDebutStr = dateDebut != null ? dateDebut.format(DATE_FORMATTER) : null;
            String dateFinStr = dateFin != null ? dateFin.format(DATE_FORMATTER) : null;

            auditLogs = auditServiceClient.searchLogs(
                acteurUsername,
                dateDebutStr,
                dateFinStr,
                selectedTypeAction,
                ressourceType,
                succes,
                currentPage,
                pageSize
            );

            totalRecords = auditLogs.size();
            addSuccessMessage("Recherche effectuée: " + totalRecords + " résultat(s) trouvé(s)");
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de la recherche: " + e.getMessage());
            addErrorMessage("Erreur lors de la recherche: " + e.getMessage());
        }
    }

    /**
     * Charger les logs par acteur
     */
    public void loadLogsByActeur(String username) {
        try {
            auditLogs = auditServiceClient.getLogsByActeur(username, 100);
            totalRecords = auditLogs.size();
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement: " + e.getMessage());
            addErrorMessage("Erreur lors du chargement: " + e.getMessage());
        }
    }

    /**
     * Charger les logs par realm
     */
    public void loadLogsByRealm(String realmName) {
        try {
            String dateDebutStr = dateDebut != null ? dateDebut.format(DATE_FORMATTER) : null;
            String dateFinStr = dateFin != null ? dateFin.format(DATE_FORMATTER) : null;

            auditLogs = auditServiceClient.getLogsByRealm(
                realmName,
                dateDebutStr,
                dateFinStr,
                currentPage,
                pageSize
            );

            totalRecords = auditLogs.size();
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement: " + e.getMessage());
            addErrorMessage("Erreur lors du chargement: " + e.getMessage());
        }
    }

    /**
     * Charger les statistiques
     */
    public void loadStatistics() {
        try {
            String dateDebutStr = dateDebut != null ? dateDebut.format(DATE_FORMATTER) : null;
            String dateFinStr = dateFin != null ? dateFin.format(DATE_FORMATTER) : null;

            actionStatistics = auditServiceClient.getActionStatistics(dateDebutStr, dateFinStr);
            userActivityStatistics = auditServiceClient.getUserActivityStatistics(dateDebutStr, dateFinStr);
            AuditServiceClient.CountResponse failureResponse = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr);
            failureCount = failureResponse != null ? failureResponse.count : 0L;
            AuditServiceClient.CountResponse successResponse = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr);
            successCount = successResponse != null ? successResponse.count : 0L;
        } catch (Exception e) {
            LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
        }
    }

    /**
     * Exporter les logs en CSV
     */
    public void exportToCSV() {
        try {
            String dateDebutStr = dateDebut != null ? dateDebut.format(DATE_FORMATTER) : null;
            String dateFinStr = dateFin != null ? dateFin.format(DATE_FORMATTER) : null;

            String csv = auditServiceClient.exportLogsToCSV(dateDebutStr, dateFinStr);

            // Télécharger le fichier CSV
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ExternalContext externalContext = facesContext.getExternalContext();

            String filename = "audit-logs-" +
                LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd_HHmmss")) +
                ".csv";

            externalContext.setResponseContentType("text/csv; charset=UTF-8");
            externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

            java.io.OutputStream output = externalContext.getResponseOutputStream();
            output.write(csv.getBytes(java.nio.charset.StandardCharsets.UTF_8));
            output.flush();

            facesContext.responseComplete();
            LOGGER.info("Export CSV généré avec succès: " + filename);
        } catch (java.io.IOException e) {
            LOGGER.severe("Erreur I/O lors de l'export CSV: " + e.getMessage());
            addErrorMessage("Erreur lors du téléchargement: " + e.getMessage());
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de l'export CSV: " + e.getMessage());
            addErrorMessage("Erreur lors de l'export: " + e.getMessage());
        }
    }

    /**
     * Réinitialiser les filtres
     */
    public void resetFilters() {
        acteurUsername = null;
        dateDebut = null;
        dateFin = null;
        selectedTypeAction = null;
        ressourceType = null;
        succes = null;
        currentPage = 0;
        auditLogs.clear();
    }

    /**
     * Page précédente
     */
    public void previousPage() {
        if (currentPage > 0) {
            currentPage--;
            searchLogs();
        }
    }

    /**
     * Page suivante
     */
    public void nextPage() {
        currentPage++;
        searchLogs();
    }

    /**
     * Charger les realms disponibles depuis Keycloak
     */
    private void loadRealms() {
        try {
            LOGGER.info("Chargement des realms disponibles depuis Keycloak");
            List<String> realms = realmServiceClient.getAllRealms();
            
            if (realms == null || realms.isEmpty()) {
                LOGGER.warning("Aucun realm trouvé dans Keycloak");
                availableRealms = Collections.emptyList();
            } else {
                availableRealms = new ArrayList<>(realms);
                LOGGER.info("Realms disponibles chargés depuis Keycloak: " + availableRealms.size());
            }
        } 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: liste vide plutôt que des données fictives
            availableRealms = Collections.emptyList();
        }
    }

    // Méthodes utilitaires
    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));
    }
}

