package dev.lions.unionflow.client.view;

import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;

import java.io.Serializable;
import java.time.Instant;
import java.time.Duration;
import java.util.logging.Logger;

/**
 * Bean de monitoring de session utilisateur en temps réel
 * Calcule le temps restant avant expiration du token JWT
 *
 * @author UnionFlow Team
 * @version 1.0
 */
@Named("sessionMonitor")
@SessionScoped
public class SessionMonitorBean implements Serializable {

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

    // Temps d'inactivité maximum en secondes (30 minutes par défaut)
    private static final long DEFAULT_INACTIVITY_TIMEOUT = 1800;

    private Instant lastActivityTime;
    private long inactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT;

    public SessionMonitorBean() {
        this.lastActivityTime = Instant.now();
    }

    /**
     * Met à jour le timestamp de la dernière activité
     */
    public void updateActivity() {
        this.lastActivityTime = Instant.now();
    }

    /**
     * Calcule le temps d'inactivité en secondes
     */
    public long getInactivitySeconds() {
        if (lastActivityTime == null) {
            lastActivityTime = Instant.now();
            return 0;
        }
        return Duration.between(lastActivityTime, Instant.now()).getSeconds();
    }

    /**
     * Calcule le temps restant avant expiration en minutes
     */
    public long getRemainingMinutes() {
        long inactivitySeconds = getInactivitySeconds();
        long remainingSeconds = inactivityTimeout - inactivitySeconds;

        if (remainingSeconds < 0) {
            return 0;
        }

        return remainingSeconds / 60;
    }

    /**
     * Calcule le temps restant avant expiration en secondes (pour le timer)
     */
    public long getRemainingSeconds() {
        long inactivitySeconds = getInactivitySeconds();
        long remainingSeconds = inactivityTimeout - inactivitySeconds;

        return Math.max(0, remainingSeconds);
    }

    /**
     * Formate le temps restant en format mm:ss
     */
    public String getFormattedRemainingTime() {
        long totalSeconds = getRemainingSeconds();
        long minutes = totalSeconds / 60;
        long seconds = totalSeconds % 60;
        return String.format("%02d:%02d", minutes, seconds);
    }

    /**
     * Retourne le pourcentage de temps écoulé (pour une barre de progression)
     */
    public int getSessionProgressPercent() {
        long inactivitySeconds = getInactivitySeconds();
        if (inactivityTimeout == 0)
            return 0;

        int percent = (int) ((inactivitySeconds * 100) / inactivityTimeout);
        return Math.min(100, Math.max(0, percent));
    }

    /**
     * Vérifie si la session est proche de l'expiration (moins de 5 minutes)
     */
    public boolean isSessionExpiringSoon() {
        return getRemainingMinutes() <= 5;
    }

    /**
     * Vérifie si la session est expirée
     */
    public boolean isSessionExpired() {
        return getRemainingSeconds() == 0;
    }

    /**
     * Retourne la classe CSS pour l'indicateur de temps (couleur)
     */
    public String getTimeIndicatorClass() {
        long minutes = getRemainingMinutes();
        if (minutes <= 3) {
            return "text-red-600 font-bold"; // Rouge critique
        } else if (minutes <= 5) {
            return "text-orange-600 font-semibold"; // Orange warning
        } else if (minutes <= 10) {
            return "text-yellow-600"; // Jaune attention
        } else {
            return "text-green-600"; // Vert OK
        }
    }

    /**
     * Retourne l'icône appropriée selon le temps restant
     */
    public String getTimeIndicatorIcon() {
        long minutes = getRemainingMinutes();
        if (minutes <= 3) {
            return "pi pi-exclamation-triangle";
        } else if (minutes <= 5) {
            return "pi pi-clock";
        } else {
            return "pi pi-check-circle";
        }
    }

    // Getters et Setters

    public long getInactivityTimeout() {
        return inactivityTimeout;
    }

    public void setInactivityTimeout(long inactivityTimeout) {
        this.inactivityTimeout = inactivityTimeout;
    }

    public Instant getLastActivityTime() {
        return lastActivityTime;
    }
}
