<?php

namespace Sitecake\Http;

/**
 * Thin wrapper around PHP native sessions.
 * Replaces Symfony's Session / SessionInterface for SiteCake's needs.
 */
class Session
{
    private bool $started = false;

    /** Lazily start the session. */
    public function start(): void
    {
        if (!$this->started && session_status() !== PHP_SESSION_ACTIVE) {
            // LOW-6: Align GC lifetime with SessionManager timeout (10000 s)
            ini_set('session.gc_maxlifetime', 10000);

            // HIGH-2: Secure session cookie settings
            session_set_cookie_params([
                'lifetime' => 0,
                'path'     => '/',
                'secure'   => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
                'httponly' => true,
                'samesite' => 'Strict',
            ]);

            session_start();
            $this->started = true;

            // HIGH-3: Generate CSRF token if not already set
            if (empty($_SESSION['csrf_token'])) {
                $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            }
        }
    }

    /**
     * Return the current CSRF token, generating one if the session is not yet started.
     */
    public static function getCsrfToken(): string
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
            if (empty($_SESSION['csrf_token'])) {
                $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            }
        }
        return $_SESSION['csrf_token'] ?? '';
    }

    public function has(string $name): bool
    {
        $this->start();
        return isset($_SESSION[$name]);
    }

    public function get(string $name, $default = null)
    {
        $this->start();
        return $_SESSION[$name] ?? $default;
    }

    public function set(string $name, $value): void
    {
        $this->start();
        $_SESSION[$name] = $value;
    }

    /**
     * Destroy the current session (equivalent to Symfony Session::invalidate).
     */
    public function invalidate(int $lifetime = null): void
    {
        $this->start();
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params['path'],
                $params['domain'],
                $params['secure'],
                $params['httponly']
            );
        }
        session_destroy();
        $this->started = false;
    }
}
