<?php

declare(strict_types=1);

use App\Http\Middleware\EnsureUserIsActive;
use App\Http\Middleware\EnsureUserIsMaster;
use App\Http\Middleware\ForcePasswordChange;
use App\Http\Middleware\SecurityHeaders;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withSchedule(function (Schedule $schedule): void {
        // 08:00 server time — early enough to act on before most of the
        // working day starts, and the command itself is a no-op in seconds
        // when digest emails are turned off or nothing is due.
        $schedule->command('ams:send-warranty-digest')->dailyAt('08:00');

        // Weekly, off-hours: retention pruning is a maintenance task, not a
        // time-sensitive one, and a quiet Sunday is the last time anyone is
        // relying on a same-day audit entry that is also years past the
        // retention window.
        $schedule->command('ams:prune-audit-logs')->weeklyOn(0, '02:00');
    })
    ->withMiddleware(function (Middleware $middleware): void {
        // Defensive response headers on every request, including error pages.
        $middleware->append(SecurityHeaders::class);

        /*
         | Route middleware aliases.
         |
         | The standard stack for an authenticated screen is:
         |     ['auth', 'active', 'password.change']
         |
         | and master-only areas append 'master'. Order matters: `active` needs
         | a resolved user, and a disabled account must be signed out before it
         | is asked to choose a new password.
         */
        $middleware->alias([
            'active' => EnsureUserIsActive::class,
            'master' => EnsureUserIsMaster::class,
            'password.change' => ForcePasswordChange::class,
        ]);

        /*
         | Guests are redirected to a literal path rather than route('login'),
         | because routes are registered phase by phase and a redirect must
         | never depend on registration order.
         */
        $middleware->redirectGuestsTo(
            fn (Request $request): string => (string) config('ams.auth.login_path'),
        );

        $middleware->redirectUsersTo(
            fn (Request $request): string => (string) config('ams.auth.home_path'),
        );
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        /*
         | Never leak the existence or shape of internal records through an
         | exception message. Views in resources/views/errors render a plain
         | branded page for each status code.
         */
        $exceptions->dontReportDuplicates();
    })
    ->create();
