<?php

use App\Http\Middleware\HandleInertiaRequests;
use App\Http\Middleware\RefreshApiToken;
use App\Http\Middleware\SanctumOrTrustedOrigin;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets;
use Inertia\Inertia;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Spatie\Permission\Middleware\PermissionMiddleware;
use Spatie\Permission\Middleware\RoleMiddleware;
use Spatie\Permission\Middleware\RoleOrPermissionMiddleware;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;


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',
        apiPrefix: '',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->web(append: [
            HandleInertiaRequests::class,
            AddLinkHeadersForPreloadedAssets::class,
            RefreshApiToken::class
        ]);
        $middleware->alias([
            'role'               => RoleMiddleware::class,
            'permission'         => PermissionMiddleware::class,
            'role_or_permission' => RoleOrPermissionMiddleware::class,
            'sanctum.or.trusted' => SanctumOrTrustedOrigin::class,
        ]);
        //
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        $exceptions->render(function (NotFoundHttpException $e, Request $request) {
            if ($request->getHost() !== config('app.api_domain')) {
                return null;
            }

            if ($e->getPrevious() instanceof ModelNotFoundException) {
                return response()->json(['message' => 'Resource not found.'], 404);
            }

            return response()->json(['message' => 'Not found.'], 404);
        });

        $exceptions->respond(function ($response, Throwable $e, Request $request) {
            $status = $response->getStatusCode();

            // API domain: never touch the response, let Laravel's own JSON rendering stand.
            if ($request->getHost() === config('app.api_domain')) {
                return $response;
            }

            $errors = [
                403 => [
                    'title'   => "The Cockpit is Off Limits",
                    'message' => 'You don\'t have permission to access this page.',
                ],
                404 => [
                    'title'   => 'You Flight Has Been Cancelled',
                    'message' => 'The page you are looking for doesn\'t exist or has been moved.',
                ],
                419 => [
                    'title'   => 'Page Expired',
                    'message' => 'Your session has expired. Please refresh the page and try again.',
                ],
                429 => [
                    'title'   => 'Too Many Requests',
                    'message' => 'You\'re making too many requests. Please slow down and try again.',
                ],
                500 => [
                    'title'   => 'This Plane Has Made An Emergency Landing',
                    'message' => 'Something went wrong on our end. Please try again later.',
                ],
                503 => [
                    'title'   => 'Service Unavailable',
                    'message' => 'We\'re down for maintenance. Please check back soon.',
                ],
            ];

            $isLocal = app()->environment(['local', 'testing']);
            $friendlyErrorsOnLocal = [404, 403];

            $shouldHandle = isset($errors[$status]) && (
                    !$isLocal || in_array($status, $friendlyErrorsOnLocal)
                );

            if (!$shouldHandle) {
                return $response;
            }

            return Inertia::render('Error', [
                'statusCode'    => $status,
                'statusTitle'   => $errors[$status]['title'],
                'statusMessage' => $errors[$status]['message'],
                'auth'          => [
                    'user'        => $request->user(),
                    'roles'       => $request->user()?->getRoleNames() ?? [],
                    'permissions' => $request->user()?->getAllPermissions()->pluck('name') ?? [],
                ],
            ])
                ->toResponse($request)
                ->setStatusCode($status);
        })
            ->shouldRenderJsonWhen(function ($request, Throwable $e) {
                if ($request->getHost() === config('app.api_domain')) {
                    return true;
                }

                return $request->expectsJson();
            });
    })
    ->create();
