<?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\InstallAccessGuard;
use Acms\Services\Setup\InstallStatus;
use Acms\Services\Setup\SetupCsrfToken;
use Acms\Services\Setup\SetupSession;

/**
 * インストール状態に応じたアクセスガード。2 モードを持つ。
 *
 * - REQUIRE_INSTALLED（メンテナンスメニュー）: 未インストールなら install.php へリダイレクト。
 * - BLOCK_REINSTALL（W1・install）: インストール済みは有効な setup トークンを持つ正規セッション
 *   （インストール続行中）だけ許可し、外部からの再実行を GET/POST 問わず遮断する。判定は既存の
 *   {@see InstallAccessGuard} に委譲。
 */
final class InstalledGuardMiddleware implements Middleware
{
    public const REQUIRE_INSTALLED = 'require';
    public const BLOCK_REINSTALL = 'block';

    public function __construct(
        private readonly InstallStatus $status,
        private readonly string $mode,
        private readonly ?SetupSession $session = null,
    ) {
    }

    public function process(Request $request, callable $next): Response
    {
        $installed = $this->status->isInstalled();

        if ($this->mode === self::REQUIRE_INSTALLED) {
            if (!$installed) {
                return Response::redirect('./install.php');
            }
            return $next($request);
        }

        // BLOCK_REINSTALL（W1）
        $hasValidToken = $this->session !== null
            && SetupCsrfToken::matches($this->session->formToken(), $request->post()->get('setupFormToken'));
        if (!(new InstallAccessGuard())->isAllowed($installed, $hasValidToken)) {
            return Response::html('system has already installed.', 403);
        }
        return $next($request);
    }
}
