<?php

namespace App\Support\Middleware;

use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\WorkspaceHubRegistry;
use App\Support\Navigation\WorkspaceSidebarNavigation;
use App\Support\OperateHub\OperateHubShell;
use App\Support\Workspaces\WorkspaceContext;
use Closure;
use Filament\Facades\Filament;
use Filament\Navigation\NavigationBuilder;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureEnvironmentContextSelected
{
    /**
     * @param  Closure(Request): Response  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $panel = Filament::getCurrentOrDefaultPanel();
        $resolvedContext = app(OperateHubShell::class)->resolvedContext($request);

        $path = '/'.ltrim($request->path(), '/');

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

        $existingTenant = Filament::getTenant();
        if ($existingTenant instanceof ManagedEnvironment && $workspaceId !== null && (int) $existingTenant->workspace_id !== (int) $workspaceId) {
            Filament::setTenant(null, true);
            $existingTenant = null;
        }

        $user = $request->user();
        if ($existingTenant instanceof ManagedEnvironment && $user instanceof User && ! $user->canAccessTenant($existingTenant)) {
            Filament::setTenant(null, true);
            $existingTenant = null;
        }

        if ($existingTenant instanceof ManagedEnvironment && ($existingTenant->isRemovedFromWorkspace() || $existingTenant->workspace?->isClosed())) {
            Filament::setTenant(null, true);
            $existingTenant = null;
        }

        if ($this->isLivewireUpdatePath($path)) {
            $refererPath = parse_url((string) $request->headers->get('referer', ''), PHP_URL_PATH) ?? '';
            $refererPath = '/'.ltrim((string) $refererPath, '/');

            if ($this->isCanonicalWorkspaceRecordViewerPath($refererPath)) {
                $this->configureNavigationForRequest($panel, $request);

                return $next($request);
            }

            if ($this->isWorkspaceScopedPageWithTenant($refererPath)) {
                $this->configureNavigationForRequest($panel, $request);

                return $next($request);
            }
        }

        if ($this->isCanonicalWorkspaceRecordViewerPath($path)) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        if (in_array($path, ['/admin/findings/my-work', '/admin/findings/intake', '/admin/findings/hygiene'], true)) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        if (preg_match('#^/admin/workspaces/[^/]+/operations(?:/[^/]+)?$#', $path) === 1) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        if (
            ! $resolvedContext->hasTenant()
            && $this->adminPathRequiresTenantSelection($path)
        ) {
            if ($this->requestHasExplicitTenantHint($request)) {
                abort(404);
            }

            $workspace = $workspaceContext->currentWorkspace($request);

            if ($workspace !== null) {
                return redirect()->route('admin.workspace.managed-environments.index', ['workspace' => $workspace]);
            }

            return redirect()->route('filament.admin.pages.choose-environment');
        }

        if ($resolvedContext->pageCategory === AdminSurfaceScope::EnvironmentBound && ! $resolvedContext->hasTenant()) {
            abort(404);
        }

        if ($resolvedContext->hasTenant() && $resolvedContext->tenant?->isRemovedFromWorkspace() && str_starts_with($path, '/admin/workspaces/')) {
            abort(404);
        }

        if ($resolvedContext->hasTenant() && $resolvedContext->tenant?->workspace?->isClosed() && str_starts_with($path, '/admin/workspaces/')) {
            abort(404);
        }

        if (
            $resolvedContext->hasTenant()
            && (
                ! $this->isWorkspaceScopedPageWithTenant($path)
                && $resolvedContext->pageCategory === AdminSurfaceScope::EnvironmentBound
            )
        ) {
            Filament::setTenant($resolvedContext->tenant, true);
        } elseif (! $resolvedContext->hasTenant()) {
            Filament::setTenant(null, true);
        }

        if (
            str_starts_with($path, '/admin/workspaces/')
            || in_array($path, ['/admin', '/admin/choose-workspace', '/admin/choose-environment', '/admin/no-access', '/admin/alerts', '/admin/audit-log', '/admin/onboarding', '/admin/settings/workspace', '/admin/findings/my-work', '/admin/findings/intake', '/admin/findings/hygiene'], true)
        ) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        if (filled(Filament::getTenant())) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        if (! $user instanceof User) {
            $this->configureNavigationForRequest($panel, $request);

            return $next($request);
        }

        $this->configureNavigationForRequest($panel, $request);

        return $next($request);
    }

    private function configureNavigationForRequest(\Filament\Panel $panel, Request $request): void
    {
        if (NavigationScope::isEnvironmentSurface($request)) {
            $panel->navigation(true);

            return;
        }

        $panel->navigation(function (WorkspaceSidebarNavigation $navigation): NavigationBuilder {
            return $navigation->build();
        });
    }

    private function isWorkspaceScopedPageWithTenant(string $path): bool
    {
        return preg_match('#^/admin/workspaces/[^/]+/environments/[^/]+/(required-permissions|diagnostics|access-scopes|baseline-compare)$#', $path) === 1;
    }

    private function isLivewireUpdatePath(string $path): bool
    {
        return preg_match('#^/livewire(?:-[^/]+)?/update$#', $path) === 1;
    }

    private function isCanonicalWorkspaceRecordViewerPath(string $path): bool
    {
        return AdminSurfaceScope::fromPath($path) === AdminSurfaceScope::CanonicalWorkspaceRecordViewer;
    }

    private function requestHasExplicitTenantHint(Request $request): bool
    {
        if (WorkspaceHubRegistry::isWorkspaceHubPath('/'.ltrim((string) $request->path(), '/'))) {
            return false;
        }

        return filled($request->query('tenant')) || filled($request->query('managed_environment_id'));
    }

    private function adminPathRequiresTenantSelection(string $path): bool
    {
        if (! str_starts_with($path, '/admin/')) {
            return false;
        }

        if (str_starts_with($path, '/admin/finding-exceptions/queue')) {
            return false;
        }

        if (str_starts_with($path, '/admin/findings/my-work')) {
            return false;
        }

        if (str_starts_with($path, '/admin/findings/intake')) {
            return false;
        }

        if (str_starts_with($path, '/admin/findings/hygiene')) {
            return false;
        }

        return preg_match('#^/admin/(inventory|policies|policy-versions|backup-sets|backup-schedules|findings|finding-exceptions)(/|$)#', $path) === 1;
    }
}
