<?php

declare(strict_types=1);

namespace App\Core;

final class Auth
{
    private const SESSION_KEY = 'user';
    private const TIMEOUT_SECONDS = 1800;

    /**
     * @param array<string,mixed> $user
     */
    public static function login(array $user): void
    {
        $userId = (int)($user['id'] ?? 0);

        if ($userId <= 0) {
            throw new \InvalidArgumentException(
                'Utilisateur invalide.'
            );
        }

        if (session_status() === PHP_SESSION_ACTIVE) {
            session_regenerate_id(true);
        }

        Session::set(self::SESSION_KEY, [
            'id' => $userId,
            'nom' => trim((string)($user['nom'] ?? '')),
            'prenom' => trim((string)($user['prenom'] ?? '')),
            'login' => trim((string)($user['login'] ?? '')),
            'email' => trim((string)($user['email'] ?? '')),
            'role' => strtoupper(
                trim((string)($user['role'] ?? 'UTILISATEUR'))
            ),
            'connected_at' => time(),
            'last_activity' => time(),
        ]);
    }

    public static function check(): bool
    {
        $user = Session::get(self::SESSION_KEY);

        if (!is_array($user)) {
            return false;
        }

        $lastActivity = (int)($user['last_activity'] ?? 0);

        if ($lastActivity <= 0) {
            self::logout();
            return false;
        }

        if ((time() - $lastActivity) > self::TIMEOUT_SECONDS) {
            self::logout();
            return false;
        }

			$now = time();

			if ($now > $lastActivity) {
				$user['last_activity'] = $now;
				Session::set(self::SESSION_KEY, $user);
			}

        return true;
    }

    /**
     * @return array<string,mixed>|null
     */
    public static function user(): ?array
    {
        if (!self::check()) {
            return null;
        }

        $user = Session::get(self::SESSION_KEY);

        return is_array($user)
            ? $user
            : null;
    }

    public static function id(): ?int
    {
        $user = self::user();

        if ($user === null) {
            return null;
        }

        $id = (int)($user['id'] ?? 0);

        return $id > 0
            ? $id
            : null;
    }

    public static function name(): string
    {
        $user = self::user();

        if ($user === null) {
            return '';
        }

        $fullName = trim(
            (string)($user['prenom'] ?? '')
            . ' '
            . (string)($user['nom'] ?? '')
        );

        if ($fullName !== '') {
            return $fullName;
        }

        return trim((string)($user['login'] ?? ''));
    }

    public static function role(): string
    {
        $user = self::user();

        if ($user === null) {
            return '';
        }

        return strtoupper(
            trim((string)($user['role'] ?? ''))
        );
    }

    public static function hasRole(string $role): bool
    {
        return self::check()
            && self::role() === strtoupper(trim($role));
    }

    /**
     * @param array<int,string> $roles
     */
    public static function hasAnyRole(array $roles): bool
    {
        if (!self::check()) {
            return false;
        }

        $normalizedRoles = array_map(
            static fn (string $role): string =>
                strtoupper(trim($role)),
            $roles
        );

        return in_array(
            self::role(),
            $normalizedRoles,
            true
        );
    }

public static function logout(): void
{
    Session::forget(self::SESSION_KEY);

    /*
     * Supprime les données sensibles éventuelles,
     * mais conserve les messages flash utilisés
     * après la redirection vers la connexion.
     */
    foreach (array_keys($_SESSION) as $key) {
        if ($key !== '_flash') {
            unset($_SESSION[$key]);
        }
    }

    /*
     * Invalide l’ancien identifiant de session.
     */
    if (session_status() === PHP_SESSION_ACTIVE) {
        session_regenerate_id(true);
    }
}

    public static function isExpired(): bool
    {
        $user = Session::get(self::SESSION_KEY);

        if (!is_array($user)) {
            return false;
        }

        $lastActivity = (int)($user['last_activity'] ?? 0);

        return $lastActivity > 0
            && (time() - $lastActivity) > self::TIMEOUT_SECONDS;
    }

    public static function timeoutMinutes(): int
    {
        return (int)(self::TIMEOUT_SECONDS / 60);
    }
}