<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Гейт SaaS-admin зоны (/api/admin/*) — audit-находка J2.
 *
 * СТОПГЭП (2026-05-25): защита боевой админ-зоны (/admin + /api/admin/*)
 * перенесена на уровень nginx — отдельный HTTP Basic Auth с собственным
 * паролем (`/etc/nginx/.htpasswd-admin`, location ^~ /admin и ^~ /api/admin).
 * Поэтому middleware больше не закрывает зону на проде: дверь держит nginx.
 *
 * Ранее (Sprint 3F) здесь был fail-closed 503 вне dev/testing — он закрывал
 * всю админку на проде наглухо, т.к. настоящий saas-admin SSO (Yandex 360)
 * ещё не готов (гейтится Б-1 + DO-4). Замок 503 снят осознанно: оголять
 * /api/admin/* в интернет нельзя, но nginx-пароль её прикрывает.
 *
 * admin_user_id для audit-trail по-прежнему резолвится трейтом
 * ResolvesAdminUserId (стаб super_admin) — это отдельная зона.
 *
 * G7-B: пока активен impersonation (маркер сессии ИЛИ машинный ключ) —
 * вход в saas-admin зону запрещён (запрет эскалации к другим тенантам).
 *
 * M-1 (приёмка 21.06): nginx-дверь дополнена app-слойным fail-closed гейтом по
 * REMOTE_USER + config-allowlist. Закрывает обходы front-controller'а
 * (/index.php/api/admin, /API/admin), где nginx basic-auth не применяется и
 * REMOTE_USER пуст. См. config/admin.php и spec 2026-06-21-m1-admin-gate-fail-closed.
 *
 * TODO (после Б-1 + DO-4): заменить nginx-дверь на настоящий saas-admin
 * guard (Yandex 360 SSO-сессия + роль).
 */
class EnsureSaasAdmin
{
    public function handle(Request $request, Closure $next): Response
    {
        // G7-B: пока активен impersonation (маркер сессии ИЛИ машинный ключ) —
        // вход в saas-admin зону запрещён (запрет эскалации к другим тенантам).
        $hasMarker = $request->hasSession() && $request->session()->has('impersonation');
        $hasBearer = str_starts_with((string) $request->header('Authorization', ''), 'Bearer lpimp_');
        if ($hasMarker || $hasBearer) {
            abort(403, 'Во время сессии impersonation доступ в админ-зону запрещён.');
        }

        // M-1 (приёмка 21.06): fail-closed гейт. REMOTE_USER непуст только у запросов,
        // прошедших nginx admin-basic-auth (^~ /admin, ^~ /api/admin); обходы через
        // front-controller (/index.php/api/admin, /API/admin) попадают в auth_basic off
        // → REMOTE_USER пуст → 403. В local/testing гейт выключен (см. config/admin.php).
        if (config('admin.basic_auth_gate')) {
            $remoteUser = (string) $request->server('REMOTE_USER', '');
            $allowlist = (array) config('admin.basic_auth_allowlist', []);
            if ($remoteUser === '' || ! in_array($remoteUser, $allowlist, true)) {
                abort(403, 'Доступ в админ-зону запрещён.');
            }
        }

        return $next($request);
    }
}
