<?php

class Session
{
    private static bool $started = false;

    public static function start(): void
    {
        if (self::$started || session_status() === PHP_SESSION_ACTIVE) {
            return;
        }

        // Secure session configuration
        $lifetime = Env::int('SESSION_LIFETIME', 3600); // 1 hour default
        $secure = Env::bool('SESSION_SECURE_COOKIE', false);
        $httponly = Env::bool('SESSION_HTTPONLY_COOKIE', true);
        $samesite = Env::get('SESSION_SAMESITE_COOKIE', 'Strict');

        // Set session cookie parameters
        session_set_cookie_params([
            'lifetime' => $lifetime,
            'path' => '/',
            'domain' => '',
            'secure' => $secure,
            'httponly' => $httponly,
            'samesite' => $samesite
        ]);

        // Set session name for security
        session_name('NOTAPHILYCATALOGUE_SESSION');

        // Start session
        session_start();

        // Regenerate session ID to prevent session fixation
        if (!self::has('session_regenerated')) {
            session_regenerate_id(true);
            self::set('session_regenerated', true);
            self::set('session_start_time', time());
        }

        // Check session timeout
        $startTime = self::get('session_start_time', time());
        if (time() - $startTime > $lifetime) {
            self::destroy();
            return;
        }

        self::$started = true;
    }

    public static function regenerate(): void
    {
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_regenerate_id(true);
            self::set('session_regenerated', true);
            self::set('session_start_time', time());
        }
    }

    public static function set(string $key, mixed $value): void
    {
        $_SESSION[$key] = $value;
    }

    public static function get(string $key, mixed $default = null): mixed
    {
        return $_SESSION[$key] ?? $default;
    }

    public static function has(string $key): bool
    {
        return isset($_SESSION[$key]);
    }

    public static function remove(string $key): void
    {
        unset($_SESSION[$key]);
    }

    public static function destroy(): void
    {
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_destroy();
        }
        $_SESSION = [];
        self::$started = false;

        // Clear session cookie
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000,
                $params['path'], $params['domain'],
                $params['secure'], $params['httponly']
            );
        }
    }

    public static function isLoggedIn(): bool
    {
        return self::has('user_id');
    }

    public static function getUserId(): ?int
    {
        return self::get('user_id');
    }

    public static function flash(string $key, mixed $value): void
    {
        $_SESSION['_flash'][$key] = $value;
    }

    public static function getFlash(string $key, mixed $default = null): mixed
    {
        $value = $_SESSION['_flash'][$key] ?? $default;
        unset($_SESSION['_flash'][$key]);
        return $value;
    }

    public static function hasFlash(string $key): bool
    {
        return isset($_SESSION['_flash'][$key]);
    }

    public static function generateCsrfToken(): string
    {
        $token = bin2hex(random_bytes(32));
        self::set('csrf_token', $token);
        return $token;
    }

    public static function getCsrfToken(): string
    {
        if (!self::has('csrf_token')) {
            return self::generateCsrfToken();
        }
        return self::get('csrf_token');
    }

    public static function verifyCsrfToken(string $token): bool
    {
        return hash_equals(self::get('csrf_token', ''), $token);
    }
}
