<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class CloseSessionEarly
{
    /**
     * Release the authenticated user's session before heavy GET/HEAD controllers run.
     *
     * The middleware must run AFTER auth/permission middleware. It is intentionally no-op
     * for POST/PUT/PATCH/DELETE so flash data and form validation sessions stay normal.
     */
    public function handle(Request $request, Closure $next)
    {
        if ($this->shouldReleaseSession($request)) {
            $this->releaseSession($request);
        }

        return $next($request);
    }

    private function shouldReleaseSession(Request $request): bool
    {
        return $request->hasSession()
            && in_array($request->method(), ['GET', 'HEAD'], true)
            && !$request->ajax();
    }

    private function releaseSession(Request $request): void
    {
        try {
            /*
             * Laravel's session store save() persists the session early. This prevents
             * same-user tabs from waiting for a slow dashboard/report/settings request.
             */
            $request->session()->save();

            /*
             * If PHP's native session handler was started by the server/runtime, close
             * it too. This is safe when no native session is active.
             */
            if (function_exists('session_status') && session_status() === PHP_SESSION_ACTIVE) {
                @session_write_close();
            }
        } catch (\Throwable $e) {
            Log::warning('NGBVD early session release skipped.', [
                'path' => $request->path(),
                'message' => $e->getMessage(),
            ]);
        }
    }
}
