<?php
/**
 * Antara — CSRF token helpers backed by the user session.
 * One token per session is enough since cookies are SameSite=Lax + HttpOnly.
 *
 * Usage:
 *   AntaraCsrf::token();                          // emit on the page
 *   AntaraCsrf::assertValid($token);              // throws on mismatch
 *   AntaraCsrf::assertFromHeaderOrBody($payload); // for fetch JSON requests
 */

require_once __DIR__ . '/../auth/session.php';

final class AntaraCsrf
{
    private const SESSION_KEY = '_csrf_token';

    public static function token(): string
    {
        AntaraSession::start();
        if (empty($_SESSION[self::SESSION_KEY])) {
            $_SESSION[self::SESSION_KEY] = bin2hex(random_bytes(32));
        }
        return $_SESSION[self::SESSION_KEY];
    }

    public static function rotate(): string
    {
        AntaraSession::start();
        $_SESSION[self::SESSION_KEY] = bin2hex(random_bytes(32));
        return $_SESSION[self::SESSION_KEY];
    }

    public static function isValid(?string $token): bool
    {
        if ($token === null || $token === '') return false;
        AntaraSession::start();
        $expected = $_SESSION[self::SESSION_KEY] ?? '';
        return $expected !== '' && hash_equals($expected, $token);
    }

    public static function assertValid(?string $token): void
    {
        if (!self::isValid($token)) {
            http_response_code(419);
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['success' => false, 'error' => 'CSRF token missing or invalid.']);
            exit;
        }
    }

    public static function assertFromHeaderOrBody(array $body = []): void
    {
        $hdr = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
        $bod = $body['csrf'] ?? '';
        $token = $hdr !== '' ? $hdr : $bod;
        self::assertValid(is_string($token) ? $token : null);
    }
}
