<?php
declare(strict_types=1);

namespace App\Core;

class Csrf
{
    private const SESSION_KEY = '_csrf_token';

    public static function token(): string
    {
        if (!Session::has(self::SESSION_KEY)) {
            Session::put(self::SESSION_KEY, bin2hex(random_bytes(32)));
        }

        return (string) Session::get(self::SESSION_KEY);
    }

    public static function field(): string
    {
        $token = e(self::token());

        return '<input type="hidden" name="_csrf" value="' . $token . '">'
            . '<input class="hp" type="text" name="website" tabindex="-1" autocomplete="off" aria-hidden="true">';
    }

    public static function verify(?string $token = null): bool
    {
        $token ??= (string) ($_POST['_csrf'] ?? ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''));
        $sessionToken = (string) Session::get(self::SESSION_KEY, '');
        $honeypotIsEmpty = trim((string) ($_POST['website'] ?? '')) === '';

        return $honeypotIsEmpty && $sessionToken !== '' && hash_equals($sessionToken, $token);
    }

    public static function requireValid(): void
    {
        if (!self::verify()) {
            http_response_code(419);
            exit('CSRF token mismatch.');
        }
    }
}
