<?php

use App\Http\Middleware\EnsureUserIsActive;
use App\Http\Middleware\RecordRequestContext;
use App\Http\Middleware\SetLocale;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Http\Request;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Laravel\Sanctum\Http\Middleware\CheckAbilities;
use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        channels: __DIR__.'/../routes/channels.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        /*
         * The API stack, declared in full so the order is explicit rather than
         * emergent.
         *
         * Order matters in two places.
         *
         * CORS runs first, so even a rejected response carries the headers a
         * browser needs to read the error. A 429 the SPA cannot parse is a 429
         * the user experiences as a hang.
         *
         * Throttling runs BEFORE route-model binding. Binding performs database
         * lookups, so putting it first -- as the default group ordering does --
         * lets a throttled caller keep causing queries after they have been told
         * to stop, which defeats much of the point of the limit.
         *
         * Sanctum's stateful middleware sits between them: it decides whether
         * this request gets a cookie session, and the throttle key depends on
         * whether a user was resolved.
         */
        $middleware->group('api', [
            HandleCors::class,
            RecordRequestContext::class,
            'throttle:api',
            EnsureFrontendRequestsAreStateful::class,
            SubstituteBindings::class,
            SetLocale::class,
        ]);

        $middleware->alias([
            'abilities' => CheckAbilities::class,
            'ability' => CheckForAnyAbility::class,
            'active' => EnsureUserIsActive::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        $exceptions->shouldRenderJsonWhen(
            fn (Request $request) => $request->is('api/*') || $request->expectsJson(),
        );
    })->create();
