<?php

namespace App\Http\Middleware;

use App\Models\Customer;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

/**
 * Enforce customer account lifecycle on portal requests: a suspended or closed
 * customer must lose access. An active impersonation session is exempt so
 * operators can still inspect a suspended customer's portal. There is no
 * operator special case here any more: a `web`-guard user can never be an
 * operator, so the only thing left to exempt is an impersonation session.
 */
class EnsureCustomerActive
{
    public function handle(Request $request, Closure $next): Response
    {
        $user = $request->user();

        if ($user !== null && ! $request->session()->has('impersonator_id')) {
            $customer = Customer::query()->where('user_id', $user->id)->first()
                ?? Customer::query()->where('email', $user->email)->first();

            if ($customer !== null && ($customer->status === 'suspended' || $customer->status === 'closed' || $customer->closed_at !== null)) {
                Auth::logout();

                // NOT session()->invalidate(): where the console and the portal
                // share a host (shared/fallback mode — this VM's own mode), both
                // guards keep their login key in the SAME session. invalidate()
                // is flush() + migrate(true) — it discards every attribute in the
                // session, not just the 'web' guard's, so it would silently sign
                // an operator elsewhere in that same browser out of the console
                // too. regenerate() issues a new session id (no fixation risk)
                // without touching the other attributes, so the 'operator'
                // guard's own login key — untouched by the Auth::logout() call
                // above, which only logs out the default ('web') guard —
                // survives untouched. Same fix as routes/admin.php's own
                // /logout route, mirrored the other way round.
                $request->session()->regenerate();
                $request->session()->regenerateToken();

                $key = $customer->closed_at !== null || $customer->status === 'closed' ? 'auth.account_closed' : 'auth.account_suspended';

                return redirect()->route('login')->withErrors(['email' => __($key)]);
            }
        }

        return $next($request);
    }
}
