<?php

// The Master Control tenant edit page embeds the 30-preset preview dataset
// (~700KB) inline so the preview bridge can repaint both previews without
// round trips. Livewire's SupportMultipleRootElementDetection strips <script>
// blocks with a lazy `.*?<\/script>` pattern (debug builds only); on a 1MB
// block that exhausted the default 1,000,000-step pcre.backtrack_limit, the
// preg returned null, which was coerced to '' and loadHTML('') threw on every
// page visit. The bridge payload is slimmed at the source too, but a crash
// must not depend on every deployment's php.ini, so the limit is raised here.
ini_set('pcre.backtrack_limit', '10000000');

use App\Http\Middleware\CheckActiveUser;
use App\Http\Middleware\CheckPermission;
use App\Http\Middleware\EnsureCentralAdmin;
use App\Http\Middleware\EnsureCustomersEnabled;
use App\Http\Middleware\IdentifyTenant;
use App\Http\Middleware\RedirectToAccessibleHome;
use App\Http\Middleware\ResolveBranchContext;
use Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        // The app sits behind a reverse proxy that terminates TLS, so the
        // request Laravel actually sees arrives as plain HTTP. Without this,
        // url()/route() generate http:// links even on an https:// site —
        // harmless for a top-level link (browser just warns and still
        // navigates) but fatal for anything loaded as a subresource, e.g. the
        // POS "Sale Complete" modal's invoice iframe, which the browser
        // silently blocks as mixed content. trustHosts (below) already pins
        // which Host header we'll accept, so trusting every proxy for the
        // forwarded-proto/host headers is safe here.
        $middleware->trustProxies(at: '*');

        // Reject requests whose Host header isn't allowed — closes Host-header
        // spoofing. A no-op in local/testing (Laravel disables TrustHosts
        // there), so this doesn't affect dev/test.
        //
        // Path tenancy (production): tenancy lives in the URL, so exactly ONE
        // host is served — the wildcard subdomain pattern is dropped and the
        // wildcard TLS certificate it existed for goes away with it
        // (docs/path-based-tenancy-plan.md Phases 2+7).
        $middleware->trustHosts(at: function () {
            if (config('tenancy.routing') === 'path') {
                return ['^'.preg_quote((string) config('tenancy.app_domain'), '#').'$'];
            }

            $appDomain = config('tenancy.app_domain');
            $centralDomain = config('tenancy.central_domain');

            $patterns = array_map(
                fn (string $domain) => '^'.preg_quote($domain, '#').'$',
                array_values(array_unique(array_filter([$appDomain, $centralDomain]))),
            );

            if ($appDomain) {
                $patterns[] = '^(.+\.)?'.preg_quote($appDomain, '#').'$';
            }

            return $patterns;
        }, subdomains: false);

        $middleware->alias([
            'can_do' => CheckPermission::class,
            'check_active' => CheckActiveUser::class,
            'central' => EnsureCentralAdmin::class,
            'customers_enabled' => EnsureCustomersEnabled::class,
        ]);

        // Both Filament panels (central + app) sit behind the `web` middleware
        // group, so this pipeline applies to both. IdentifyTenant marks central
        // vs. resolves the tenant before ResolveBranchContext runs (which
        // queries the now tenant-scoped Branch model). RedirectToAccessibleHome
        // and ResolveBranchContext are tenant-panel-only in effect (they no-op
        // for guests / are meaningless on the central host) but harmless to
        // run everywhere, matching the source app's single shared web pipeline.
        $middleware->web(append: [
            IdentifyTenant::class,
            RedirectToAccessibleHome::class,
            ResolveBranchContext::class,
        ]);

        // IdentifyTenant binds the active tenant onto CurrentContext, which the
        // TenantScope needs to resolve the authenticated User. Framework
        // middleware priority otherwise sorts Authenticate (the `auth` middleware,
        // which Filament's panel auth also uses) ahead of our appended
        // IdentifyTenant: on a guarded tenant route the user would then be
        // resolved with no tenant in scope, TenantScope fails closed (1=0), the
        // guard sees a guest and redirects to login — which bounces back,
        // looping. Pinning IdentifyTenant before Authenticate (but still after
        // StartSession) closes the loop. Ported verbatim from leolanka-inertia.
        $middleware->prependToPriorityList(
            before: AuthenticatesRequests::class,
            prepend: IdentifyTenant::class,
        );
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();
