<?php

declare(strict_types=1);

namespace App\Middleware;

use App\Core\Csrf;
use App\Core\MiddlewareInterface;
use App\Core\Request;
use App\Core\Response;
use App\Helpers\AjaxResponse;

/**
 * CsrfMiddleware
 *
 * Applied to every POST/PUT/PATCH/DELETE route (see routes/web.php's
 * $stateChanging middleware group). Accepts the token from either a
 * classic form field (_csrf_token, via Csrf::field()) or the
 * X-CSRF-Token header (for vanilla-JS fetch() calls — see
 * Csrf::metaTag() and assets/js/main.js reading it).
 */
final class CsrfMiddleware implements MiddlewareInterface
{
    private const SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS'];

    public function handle(Request $request, callable $next): Response
    {
        if (in_array($request->method(), self::SAFE_METHODS, true)) {
            return $next($request);
        }

        $token = $request->input('_csrf_token') ?? $request->header('X-CSRF-Token');

        if (!Csrf::verify(is_string($token) ? $token : null)) {
            if ($request->isAjax() || $request->isJson()) {
                return AjaxResponse::error('Your session has expired. Please refresh the page and try again.', 419);
            }

            return Response::html('419 — Page expired. Please refresh and try again.', 419);
        }

        return $next($request);
    }
}
