<?php

namespace App\Http\Middleware;

use App\Support\AdminArea;
use App\Support\Settings;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

/**
 * Two-factor for operators, when the owner has made it compulsory.
 *
 * Off by default. ENROLMENT (admin.two-factor-setup) is exempt, because it is
 * where the operator sets two-factor up — gating it would leave nobody able
 * to satisfy the requirement. Nothing else is.
 *
 * This used to exempt the whole of admin.settings, on the theory that it was
 * "the page where two-factor is set up". That component also carries staff
 * management, site visibility, network restrictions, account changes, and
 * the two-factor policy switch itself — so an unenrolled operator got
 * unrestricted access to all of that, not just enrolment (Codex R15, P1b).
 * Enrolment has its own route and component for exactly this reason: one
 * page to exempt is one decision, not eight actions each needing to
 * remember to check.
 */
class RequireOperatorTwoFactor
{
    public function handle(Request $request, Closure $next): Response
    {
        if (! Settings::bool('console.require_2fa', false)) {
            return $next($request);
        }

        $operator = Auth::guard('operator')->user();

        if ($operator === null || $operator->two_factor_confirmed_at !== null) {
            return $next($request);
        }

        // The two pages that must stay reachable: where two-factor is
        // enrolled, and signing out. Both through AdminArea::routeIs(), not
        // a bare $request->routeIs() — a recovery hostname's routes are
        // named admin.viaN.*, and a bare check matches only the canonical
        // name, which would leave an unenrolled operator unable to sign out
        // on exactly the host that exists because the canonical one is not
        // working.
        if (AdminArea::routeIs('admin.two-factor-setup') || AdminArea::routeIs('admin.logout')) {
            return $next($request);
        }

        return redirect()->route('admin.two-factor-setup')
            ->with('status', __('admin_settings.two_factor_required'));
    }
}
