<?php
declare(strict_types=1);

namespace App;

final class SessionManager
{
    private string $sessionCookieName;
    private string $clientCookieName;

    public function __construct(private Config $config)
    {
        $prefix = $config->cookiePrefix();
        $this->sessionCookieName = $prefix . 'session';
        $this->clientCookieName  = $prefix . 'client';
    }

    public function start(): void
    {
        if (PHP_SAPI === 'cli') {
            return;
        }
        if (session_status() !== PHP_SESSION_NONE) {
            return;
        }

        session_name($this->sessionCookieName);

        $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
            || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');

        session_set_cookie_params([
            'lifetime' => 0,
            'path'     => '/',
            'domain'   => $this->config->cookieDomain(),
            'secure'   => $secure,
            'httponly' => true,
            'samesite' => 'Lax',
        ]);

        session_start();
    }

    public function ensureClientId(int $lifetimeSeconds = 31536000): string
    {
        if (PHP_SAPI === 'cli') {
            return 'cli';
        }

        $id = $_COOKIE[$this->clientCookieName] ?? null;
        if (!is_string($id) || !preg_match('/^[a-f0-9]{64}$/', $id)) {
            $id = bin2hex(random_bytes(32));

            $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
                || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');

            setcookie($this->clientCookieName, $id, [
                'expires'  => time() + $lifetimeSeconds,
                'path'     => '/',
                'domain'   => $this->config->cookieDomain(),
                'secure'   => $secure,
                'httponly' => false, // accessible to JS if needed
                'samesite' => 'Lax',
            ]);

            $_COOKIE[$this->clientCookieName] = $id;
        }

        return $id;
    }
}
