<?php
namespace App\Core;

/** Perlindungan CSRF berbasis token per sesi. */
class Csrf
{
    public const FIELD = '_token';

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

    public static function rotate(): void
    {
        $_SESSION[self::FIELD] = bin2hex(random_bytes(32));
    }

    public static function field(): string
    {
        return '<input type="hidden" name="' . self::FIELD . '" value="' . htmlspecialchars(self::token(), ENT_QUOTES, 'UTF-8') . '">';
    }

    public static function check(?string $token): bool
    {
        $expected = $_SESSION[self::FIELD] ?? '';
        return $expected !== '' && is_string($token) && hash_equals($expected, $token);
    }

    public static function verifyOrFail(): void
    {
        $token = $_POST[self::FIELD] ?? $_GET[self::FIELD] ?? ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? null);
        if (!self::check($token)) {
            Logger::warning('Token CSRF tidak valid dari IP ' . Request::ip() . ' pada ' . Request::uri());
            Response::abort(419, 'Sesi kedaluwarsa atau token keamanan tidak valid. Muat ulang halaman lalu coba lagi.');
        }
    }
}
