<?php

use App\Filament\Pages\WorkspaceOverview;
use App\Http\Controllers\AdminConsentCallbackController;
use App\Http\Controllers\Auth\EntraController;
use App\Http\Controllers\ClearEnvironmentContextController;
use App\Http\Controllers\LocalizationController;
use App\Http\Controllers\ManagedEnvironmentOnboardingController;
use App\Http\Controllers\OpenFindingExceptionsQueueController;
use App\Http\Controllers\RbacDelegatedAuthController;
use App\Http\Controllers\ReviewPackDownloadController;
use App\Http\Controllers\SelectEnvironmentController;
use App\Http\Controllers\SwitchWorkspaceController;
use App\Http\Middleware\SuppressDebugbarForSmokeRequests;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Onboarding\OnboardingDraftResolver;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\Auth\WorkspaceRole;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\Workspaces\WorkspaceContext;
use App\Support\Workspaces\WorkspaceResolver;
use Filament\Http\Middleware\Authenticate as FilamentAuthenticate;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/admin/consent/callback', AdminConsentCallbackController::class)
    ->name('admin.consent.callback');

Route::get('/admin/consent/start', ManagedEnvironmentOnboardingController::class)
    ->name('admin.consent.start');

// Avoid Filament's tenancy root redirect which otherwise sends users into legacy flows.
// when no default tenant can be resolved.
Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-selected',
])
    ->get('/admin', function (Request $request) {
        $workspace = app(WorkspaceContext::class)->currentWorkspace($request);

        if ($workspace instanceof Workspace) {
            return redirect()->route('admin.workspace.home', ['workspace' => $workspace]);
        }

        return redirect()->route('filament.admin.pages.choose-workspace');
    })
    ->name('admin.home');

Route::get('/admin/rbac/start', [RbacDelegatedAuthController::class, 'start'])
    ->name('admin.rbac.start');

Route::get('/admin/rbac/callback', [RbacDelegatedAuthController::class, 'callback'])
    ->name('admin.rbac.callback');

Route::get('/auth/entra/redirect', [EntraController::class, 'redirect'])
    ->name('auth.entra.redirect');

Route::get('/auth/entra/callback', [EntraController::class, 'callback'])
    ->middleware('throttle:entra-callback')
    ->name('auth.entra.callback');

Route::middleware(['web'])->group(function (): void {
    Route::get('/localization/context', [LocalizationController::class, 'context'])
        ->name('localization.context');

    Route::post('/localization/override', [LocalizationController::class, 'updateOverride'])
        ->name('localization.override.update');

    Route::delete('/localization/override', [LocalizationController::class, 'clearOverride'])
        ->name('localization.override.clear');
});

Route::middleware(['web', 'auth', 'ensure-correct-guard:web'])
    ->post('/users/me/locale-preference', [LocalizationController::class, 'updateUserPreference'])
    ->name('localization.preference.update');

$makeSmokeCookie = static fn () => cookie()->make(
    SuppressDebugbarForSmokeRequests::COOKIE_NAME,
    SuppressDebugbarForSmokeRequests::COOKIE_VALUE,
    120,
);

$resolveSmokeTenant = static function (?string $identifier): ?ManagedEnvironment {
    $identifier = trim((string) $identifier);

    if ($identifier === '') {
        return null;
    }

    return ManagedEnvironment::query()
        ->withTrashed()
        ->where(function ($query) use ($identifier): void {
            $query->where('slug', $identifier);

            if (ctype_digit($identifier)) {
                $query->orWhereKey((int) $identifier);
            }
        })
        ->first();
};

$resolveSmokeWorkspace = static function (?string $identifier, ?ManagedEnvironment $tenant = null): ?Workspace {
    if ($tenant instanceof ManagedEnvironment) {
        return Workspace::query()->whereKey($tenant->workspace_id)->first();
    }

    $identifier = trim((string) $identifier);

    if ($identifier === '') {
        return null;
    }

    return Workspace::query()
        ->where(function ($query) use ($identifier): void {
            $query->where('slug', $identifier);

            if (ctype_digit($identifier)) {
                $query->orWhereKey((int) $identifier);
            }
        })
        ->first();
};

$resolveSmokeRedirect = static function (?string $redirect, ?ManagedEnvironment $tenant = null): string {
    $fallback = $tenant instanceof ManagedEnvironment && ! $tenant->trashed()
        ? ManagedEnvironmentLinks::viewUrl($tenant)
        : '/admin';

    $redirect = trim((string) $redirect);

    if ($redirect === '') {
        return $fallback;
    }

    $parsedRedirect = parse_url($redirect);

    if ($parsedRedirect === false || isset($parsedRedirect['scheme']) || isset($parsedRedirect['host'])) {
        return $fallback;
    }

    $path = '/'.ltrim((string) ($parsedRedirect['path'] ?? ''), '/');

    if ($path !== '/admin' && ! str_starts_with($path, '/admin/')) {
        return $fallback;
    }

    $query = isset($parsedRedirect['query']) ? '?'.$parsedRedirect['query'] : '';
    $fragment = isset($parsedRedirect['fragment']) ? '#'.$parsedRedirect['fragment'] : '';

    return $path.$query.$fragment;
};

$resolveSmokeUser = static function (?string $email, ?Workspace $workspace = null, ?ManagedEnvironment $tenant = null): ?User {
    $email = trim((string) $email);

    if ($email !== '') {
        $user = User::query()->where('email', $email)->first();

        return $user instanceof User ? $user : null;
    }

    $scopedWorkspace = $workspace;

    if (! $scopedWorkspace instanceof Workspace && $tenant instanceof ManagedEnvironment) {
        $scopedWorkspace = Workspace::query()->whereKey($tenant->workspace_id)->first();
    }

    if (! $scopedWorkspace instanceof Workspace) {
        return null;
    }

    $rolePriority = [
        WorkspaceRole::Owner->value => 0,
        WorkspaceRole::Manager->value => 1,
        WorkspaceRole::Operator->value => 2,
        WorkspaceRole::Readonly->value => 3,
    ];

    $users = User::query()
        ->whereHas('workspaceMemberships', function ($query) use ($scopedWorkspace): void {
            $query->where('workspace_id', (int) $scopedWorkspace->getKey());
        })
        ->when($tenant instanceof ManagedEnvironment, function ($query) use ($tenant): void {
            $query->whereHas('tenantMemberships', function ($membershipQuery) use ($tenant): void {
                $membershipQuery->where('managed_environment_id', (int) $tenant->getKey());
            });
        })
        ->with(['workspaceMemberships' => function ($query) use ($scopedWorkspace): void {
            $query->where('workspace_id', (int) $scopedWorkspace->getKey());
        }])
        ->get()
        ->filter(function (User $user) use ($tenant): bool {
            return ! $tenant instanceof ManagedEnvironment || $user->canAccessTenant($tenant);
        })
        ->sortBy(function (User $user) use ($rolePriority): array {
            $role = $user->workspaceMemberships->first()?->role;

            return [
                $rolePriority[(string) $role] ?? 99,
                (int) $user->getKey(),
            ];
        })
        ->values();

    $user = $users->first();

    return $user instanceof User ? $user : null;
};

$completeSmokeLogin = static function (
    Request $request,
    ?string $email = null,
    ?string $tenantIdentifier = null,
    ?string $workspaceIdentifier = null,
    ?string $redirect = null,
) use (
    $makeSmokeCookie,
    $resolveSmokeRedirect,
    $resolveSmokeTenant,
    $resolveSmokeUser,
    $resolveSmokeWorkspace,
): \Illuminate\Http\RedirectResponse {
    $tenant = $resolveSmokeTenant($tenantIdentifier);
    $workspace = $resolveSmokeWorkspace($workspaceIdentifier, $tenant);
    $user = $resolveSmokeUser($email, $workspace, $tenant);

    abort_unless($user instanceof User, 404);

    $workspaceContext = app(WorkspaceContext::class);

    if (! $workspace instanceof Workspace) {
        $workspace = $workspaceContext->resolveInitialWorkspaceFor($user, $request);
    }

    abort_unless($workspace instanceof Workspace, 404);
    abort_unless($workspaceContext->isMember($user, $workspace), 404);

    if ($tenant instanceof ManagedEnvironment) {
        abort_unless((int) $tenant->workspace_id === (int) $workspace->getKey(), 404);
        abort_unless($user->canAccessTenant($tenant), 404);
    }

    Auth::guard('web')->login($user);
    $request->session()->regenerate();
    $request->session()->put(
        SuppressDebugbarForSmokeRequests::SESSION_KEY,
        SuppressDebugbarForSmokeRequests::COOKIE_VALUE,
    );

    $workspaceContext->setCurrentWorkspace($workspace, $user, $request);

    if ($tenant instanceof ManagedEnvironment) {
        $workspaceContext->rememberEnvironmentContext($tenant, $request);
    } else {
        $workspaceContext->clearRememberedTenantContext($request);
    }

    return redirect()
        ->to($resolveSmokeRedirect($redirect, $tenant))
        ->withCookie($makeSmokeCookie());
};

Route::get('/admin/local/smoke-login', function (Request $request) use ($completeSmokeLogin) {
    abort_unless(app()->environment(['local', 'testing']), 404);

    $fixture = config('tenantpilot.backup_health.browser_smoke_fixture');
    $defaultEmail = is_array($fixture) ? data_get($fixture, 'user.email') : null;
    $defaultTenant = is_array($fixture)
        ? (data_get($fixture, 'blocked_drillthrough.tenant_external_id') ?? data_get($fixture, 'blocked_drillthrough.managed_environment_id'))
        : null;
    $defaultWorkspace = is_array($fixture) ? data_get($fixture, 'workspace.slug') : null;

    return $completeSmokeLogin(
        $request,
        email: (string) ($request->query('email', $defaultEmail ?? '')),
        tenantIdentifier: (string) ($request->query('tenant', $defaultTenant ?? '')),
        workspaceIdentifier: (string) ($request->query('workspace', $defaultWorkspace ?? '')),
        redirect: (string) ($request->query('redirect', '')),
    );
})->name('admin.local.smoke-login');

Route::get('/admin/local/backup-health-browser-fixture-login', function (Request $request) use ($completeSmokeLogin) {
    abort_unless(app()->environment(['local', 'testing']), 404);

    $fixture = config('tenantpilot.backup_health.browser_smoke_fixture');
    $userEmail = is_array($fixture) ? data_get($fixture, 'user.email') : null;
    $tenantRouteKey = is_array($fixture)
        ? (data_get($fixture, 'blocked_drillthrough.managed_environment_id') ?? data_get($fixture, 'blocked_drillthrough.tenant_external_id'))
        : null;

    abort_unless(is_string($userEmail) && $userEmail !== '', 404);
    abort_unless(is_string($tenantRouteKey) && $tenantRouteKey !== '', 404);

    return $completeSmokeLogin(
        $request,
        email: $userEmail,
        tenantIdentifier: $tenantRouteKey,
        workspaceIdentifier: is_array($fixture) ? data_get($fixture, 'workspace.slug') : null,
    );
})->name('admin.local.backup-health-browser-fixture-login');

Route::middleware(['web', 'auth', 'ensure-correct-guard:web'])
    ->post('/admin/switch-workspace', SwitchWorkspaceController::class)
    ->name('admin.switch-workspace');

Route::middleware(['web', 'auth', 'ensure-correct-guard:web'])
    ->get('/admin/finding-exceptions/open-queue/{environment}', OpenFindingExceptionsQueueController::class)
    ->name('admin.finding-exceptions.open-queue');

Route::middleware(['web', 'auth', 'ensure-correct-guard:web', 'ensure-workspace-selected'])
    ->post('/admin/select-environment', SelectEnvironmentController::class)
    ->name('admin.select-environment');

Route::middleware(['web', 'auth', 'ensure-correct-guard:web', 'ensure-workspace-selected'])
    ->post('/admin/clear-environment-context', ClearEnvironmentContextController::class)
    ->name('admin.clear-environment-context');
Route::bind('workspace', function (string $value): Workspace {
    /** @var WorkspaceResolver $resolver */
    $resolver = app(WorkspaceResolver::class);

    $workspace = $resolver->resolve($value);

    abort_unless($workspace instanceof Workspace, 404);

    return $workspace;
});

Route::bind('onboardingDraft', function (string $value): ManagedEnvironmentOnboardingSession {
    $user = auth()->user();

    abort_unless($user instanceof \App\Models\User, 403);

    $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

    abort_unless(is_int($workspaceId), 404);

    $workspace = Workspace::query()->whereKey($workspaceId)->first();

    abort_unless($workspace instanceof Workspace, 404);

    return app(OnboardingDraftResolver::class)->resolve((int) $value, $user, $workspace);
});

$authorizeManagedTenantRoute = function (ManagedEnvironment $tenant, Request $request): void {
    $user = $request->user();

    abort_unless($user instanceof User, 403);

    $workspaceContext = app(WorkspaceContext::class);
    $workspaceId = $workspaceContext->currentWorkspaceId($request);

    abort_unless(is_int($workspaceId), 404);
    abort_unless((int) $tenant->workspace_id === $workspaceId, 404);

    $workspace = Workspace::query()->whereKey($workspaceId)->first();

    abort_unless($workspace instanceof Workspace, 404);
    abort_unless($workspaceContext->isMember($user, $workspace), 404);

    $allowed = app(TenantOperabilityService::class)->outcomeFor(
        tenant: $tenant,
        question: TenantOperabilityQuestion::EnvironmentBoundViewability,
        actor: $user,
        workspaceId: $workspaceId,
        lane: AdminSurfaceScope::EnvironmentBound->lane(),
    )->allowed;

    abort_unless($allowed, 404);
};

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
    'ensure-environment-context-selected',
])
    ->prefix('/admin/workspaces/{workspace}')
    ->group(function (): void {
        Route::get('/overview', WorkspaceOverview::class)
            ->name('admin.workspace.home');

        Route::get('/ping', fn () => response()->noContent())->name('admin.workspace.ping');
    });

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
])
    ->get('/admin/onboarding', \App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard::class)
    ->name('admin.onboarding');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
])
    ->get('/admin/onboarding/{onboardingDraft}', \App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard::class)
    ->name('admin.onboarding.draft');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-selected',
])
    ->get('/admin/workspaces/{workspace}/operations', \App\Filament\Pages\Monitoring\Operations::class)
    ->name('admin.operations.index');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-selected',
])
    ->get('/admin/evidence/overview', \App\Filament\Pages\Monitoring\EvidenceOverview::class)
    ->name('admin.evidence.overview');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-selected',
])
    ->get('/admin/evidence/overview', \App\Filament\Pages\Monitoring\EvidenceOverview::class)
    ->name('admin.evidence.overview');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-selected',
    'ensure-environment-context-selected',
])
    ->get('/admin/audit-log', \App\Filament\Pages\Monitoring\AuditLog::class)
    ->name('admin.monitoring.audit-log');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
])
    ->get('/admin/workspaces/{workspace}/operations/{run}', \App\Filament\Pages\Operations\TenantlessOperationRunViewer::class)
    ->name('admin.operations.view');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
])
    ->get('/admin/workspaces/{workspace}/environments', \App\Filament\Pages\Workspaces\ManagedEnvironmentsLanding::class)
    ->name('admin.workspace.managed-environments.index');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
    'ensure-environment-context-selected',
])
    ->get('/admin/workspaces/{workspace}/environments/{environment:slug}', \App\Filament\Pages\EnvironmentDashboard::class)
    ->name('admin.workspace.environments.show');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
    'ensure-environment-context-selected',
])
    ->get('/admin/workspaces/{workspace}/environments/{environment:slug}/diagnostics', \App\Filament\Pages\EnvironmentDiagnostics::class)
    ->name('admin.workspace.environments.diagnostics');

Route::middleware([
    'web',
    'panel:admin',
    'ensure-correct-guard:web',
    DisableBladeIconComponents::class,
    DispatchServingFilamentEvent::class,
    FilamentAuthenticate::class,
    'ensure-workspace-member',
    'ensure-environment-context-selected',
])
    ->get('/admin/workspaces/{workspace}/environments/{environment:slug}/access-scopes', \App\Filament\Resources\ManagedEnvironmentResource\Pages\ManageEnvironmentAccessScopes::class)
    ->name('admin.workspace.environments.access-scopes');

Route::middleware(['signed'])
    ->get('/admin/review-packs/{reviewPack}/download', ReviewPackDownloadController::class)
    ->name('admin.review-packs.download');

if (app()->runningUnitTests()) {
    Route::middleware(['web', 'auth', 'ensure-workspace-selected'])
        ->get('/admin/_test/workspace-context', function (Request $request) {
            $workspaceId = app(\App\Support\Workspaces\WorkspaceContext::class)->currentWorkspaceId($request);

            return response()->json([
                'workspace_id' => $workspaceId,
            ]);
        });
}
