<?php

namespace App\Http\Middleware;

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

class EnsureMaintenanceModeAccess
{
    /**
     * Durante mantenimiento solo administradores autenticados pueden usar la app.
     *
     * Debe ejecutarse después de StartSession (grupo web append, no prepend).
     *
     * @param  Closure(Request): (Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (! MaintenanceMode::enabled()) {
            if ($request->routeIs('maintenance')) {
                return redirect()->route('home');
            }

            return $next($request);
        }

        if ($request->is('up')) {
            return $next($request);
        }

        if ($request->routeIs('maintenance')) {
            return $this->handleMaintenancePage($request, $next);
        }

        if (MaintenanceMode::isAuthenticationRoute($request)) {
            return $next($request);
        }

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

        if (MaintenanceMode::allowsUser($user)) {
            return $next($request);
        }

        if ($user !== null) {
            $this->logoutUser($request);
        }

        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'La plataforma está en modo mantenimiento.',
            ], 503);
        }

        return redirect()->route('maintenance');
    }

    /**
     * @param  Closure(Request): (Response)  $next
     */
    private function handleMaintenancePage(Request $request, Closure $next): Response
    {
        $user = Auth::guard()->user();

        if (MaintenanceMode::allowsUser($user)) {
            return redirect()->route('admin.home');
        }

        if ($user !== null) {
            $this->logoutUser($request);
        }

        return $next($request);
    }

    private function logoutUser(Request $request): void
    {
        Auth::guard()->logout();

        if ($request->hasSession()) {
            $request->session()->invalidate();
            $request->session()->regenerateToken();
        }
    }
}
