<?php

namespace Acms\Services\Setup\Http\Middleware;

use Acms\Services\Setup\Http\Middleware;
use Acms\Services\Setup\Http\Request;
use Acms\Services\Setup\Http\Response;
use Acms\Services\Setup\SetupCsrfToken;
use Acms\Services\Setup\SetupSession;
use Closure;

/**
 * setup の CSRF 検証ミドルウェア（W2）。
 *
 * 旧 Surfacer / Install_Factory がインラインで行っていたトークン検証を合成可能な形にしたもの。
 * $shouldEnforce で「検証対象のリクエストか」を判定する（メンテナンス系は全 submit、install は
 * 副作用リクエストのみ、など経路ごとに差し替える）。不一致なら後続を実行せず 403 を返す。
 */
final class CsrfMiddleware implements Middleware
{
    /**
     * @param Closure(Request): bool $shouldEnforce
     */
    public function __construct(
        private readonly SetupSession $session,
        private readonly Closure $shouldEnforce,
        private readonly string $message = '不正なリクエストです。メンテナンスメニューから操作し直してください。',
    ) {
    }

    public function process(Request $request, callable $next): Response
    {
        if (($this->shouldEnforce)($request)) {
            $token = $this->session->ensureFormToken();
            if (!SetupCsrfToken::matches($token, $request->post()->get('setupFormToken'))) {
                return Response::html($this->message, 403);
            }
        }
        return $next($request);
    }
}
