<?php

declare(strict_types=1);

namespace App\Filament\Pages\Monitoring;

use App\Filament\Concerns\ClearsWorkspaceHubEnvironmentFilterState;
use App\Filament\Resources\OperationRunResource;
use App\Filament\Widgets\Operations\OperationsKpiHeader;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\ManagedEnvironmentAccessScopeResolver;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\WorkspaceHubEnvironmentFilter;
use App\Support\OperateHub\OperateHubShell;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Operations\OperationLifecyclePolicy;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\ActionSurfaceDefaults;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Pages\Page;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use UnitEnum;

class Operations extends Page implements HasForms, HasTable
{
    use ClearsWorkspaceHubEnvironmentFilterState;
    use InteractsWithForms;
    use InteractsWithTable;

    protected const MONITORING_PAGE_STATE_CONTRACT = [
        'surfaceKey' => 'operations',
        'surfaceType' => 'simple_monitoring',
        'stateFields' => [
            [
                'stateKey' => 'environment_id',
                'stateClass' => 'contextual_prefilter',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => true,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'problemClass',
                'stateClass' => 'contextual_prefilter',
                'carrier' => 'query_param',
                'queryRole' => 'scoped_deeplink',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'activeTab',
                'stateClass' => 'active',
                'carrier' => 'livewire_property',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'tableFilters',
                'stateClass' => 'shareable_restorable',
                'carrier' => 'session',
                'queryRole' => 'unsupported',
                'shareable' => false,
                'restorableOnRefresh' => true,
                'tenantSensitive' => true,
                'invalidFallback' => 'discard_and_continue',
            ],
        ],
        'hydrationRule' => [
            'precedenceOrder' => ['query', 'session', 'default'],
            'appliesOnInitialMountOnly' => true,
            'activeStateBecomesAuthoritativeAfterMount' => true,
            'clearsOnTenantSwitch' => ['environment_id', 'managed_environment_id', 'type', 'initiator_name'],
            'invalidRequestedStateFallback' => 'discard_and_continue',
        ],
        'inspectContract' => [
            'primaryModel' => 'none',
            'selectedStateKey' => null,
            'openedBy' => [],
            'presentation' => 'none',
            'shareable' => false,
            'invalidSelectionFallback' => 'discard_and_continue',
        ],
        'shareableStateKeys' => ['environment_id', 'problemClass', 'activeTab'],
        'localOnlyStateKeys' => [],
    ];

    public string $activeTab = 'all';

    /**
     * @var array<string, mixed>|null
     */
    public ?array $navigationContextPayload = null;

    protected static bool $isDiscovered = false;

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-queue-list';

    protected static string|UnitEnum|null $navigationGroup = 'Monitoring';

    protected static ?string $title = 'Operations';

    // Must be non-static
    protected string $view = 'filament.pages.monitoring.operations';

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forPage(ActionSurfaceProfile::RunLog, ActionSurfaceType::ReadOnlyRegistryReport)
            ->withDefaults(new ActionSurfaceDefaults(
                moreGroupLabel: 'More',
                exportIsDefaultBulkActionForReadOnly: false,
            ))
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Header actions preserve scope context and return navigation for the monitoring operations list.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Operation runs remain immutable on the monitoring list and intentionally omit bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'The empty state explains when no operation runs exist for the active workspace scope.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'Row navigation opens the canonical tenantless operation detail page, which owns header actions.');
    }

    /**
     * @return array<string, mixed>
     */
    public static function monitoringPageStateContract(): array
    {
        return self::MONITORING_PAGE_STATE_CONTRACT;
    }

    public static function canAccess(): bool
    {
        if (Filament::getCurrentPanel()?->getId() !== 'admin') {
            return false;
        }

        $user = auth()->user();

        if (! $user instanceof User) {
            return false;
        }

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

        if (! is_int($workspaceId)) {
            return false;
        }

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

        if (! $workspace instanceof Workspace) {
            return false;
        }

        return true;
    }

    public function mount(): void
    {
        $user = auth()->user();
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if (! $user instanceof User || ! is_int($workspaceId)) {
            abort(404);
        }

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

        if (! $workspace instanceof Workspace) {
            abort(404);
        }

        /** @var WorkspaceCapabilityResolver $resolver */
        $resolver = app(WorkspaceCapabilityResolver::class);

        if (! $resolver->isMember($user, $workspace)) {
            abort(404);
        }

        $this->navigationContextPayload = is_array(request()->query('nav')) ? request()->query('nav') : null;

        $this->resetWorkspaceHubEnvironmentFilterStateForCleanEntry(request());

        $this->mountInteractsWithTable();
        $this->resetWorkspaceHubEnvironmentFilterStateForCleanEntry(request());
        $this->applyRequestedDashboardPrefilter();
    }

    protected function getHeaderWidgets(): array
    {
        return [
            OperationsKpiHeader::class,
        ];
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        $operateHubShell = app(OperateHubShell::class);
        $navigationContext = $this->navigationContext();

        $actions = [
            Action::make('operate_hub_scope_operations')
                ->label($operateHubShell->scopeLabel(request()))
                ->color('gray')
                ->disabled(),
        ];

        $activeEnvironment = $this->currentTenantFilterId() === null
            ? $operateHubShell->activeEntitledTenant(request())
            : null;

        if ($navigationContext?->backLinkLabel !== null && $navigationContext->backLinkUrl !== null) {
            $actions[] = Action::make('operate_hub_back_to_origin_operations')
                ->label($navigationContext->backLinkLabel)
                ->icon('heroicon-o-arrow-left')
                ->color('gray')
                ->url($navigationContext->backLinkUrl);
        } elseif ($activeEnvironment instanceof ManagedEnvironment) {
            $actions[] = Action::make('operate_hub_back_to_tenant_operations')
                ->label('Back to '.$activeEnvironment->name)
                ->icon('heroicon-o-arrow-left')
                ->color('gray')
                ->url(ManagedEnvironmentLinks::viewUrl($activeEnvironment));
        }

        if ($activeEnvironment instanceof ManagedEnvironment) {
            $actions[] = Action::make('operate_hub_show_all_tenants')
                ->label(__('localization.shell.show_all_environments'))
                ->color('gray')
                ->action(function (): void {
                    Filament::setTenant(null, true);

                    app(WorkspaceContext::class)->clearLastEnvironmentId(request());

                    $this->removeTableFilter('managed_environment_id');

                    $this->redirect(OperationRunLinks::index(allTenants: true));
                });
        }

        return $actions;
    }

    /**
     * @return array{
     *     scope_label: string,
     *     scope_body: string,
     *     return_label: ?string,
     *     return_body: ?string,
     *     scope_reset_label: ?string,
     *     scope_reset_body: ?string,
     *     inspect_body: string
     * }
     */
    public function landingHierarchySummary(): array
    {
        $operateHubShell = app(OperateHubShell::class);
        $navigationContext = $this->navigationContext();
        $filteredTenant = $this->filteredTenant();
        $activeEnvironment = $filteredTenant instanceof ManagedEnvironment
            ? null
            : $operateHubShell->activeEntitledTenant(request());

        $returnLabel = null;
        $returnBody = null;

        if ($navigationContext?->backLinkLabel !== null && $navigationContext->backLinkUrl !== null) {
            $returnLabel = $navigationContext->backLinkLabel;
            $returnBody = 'Return to the originating monitoring surface without competing with the current tab, filters, or row inspection flow.';
        } elseif ($activeEnvironment instanceof ManagedEnvironment) {
            $returnLabel = 'Back to '.$activeEnvironment->name;
            $returnBody = 'Return to the tenant dashboard when you need tenant-specific context outside this workspace monitoring landing.';
        }

        return [
            'scope_label' => $operateHubShell->scopeLabel(request()),
            'scope_body' => $filteredTenant instanceof ManagedEnvironment
                ? 'The landing is workspace-scoped and filtered by an explicit environment filter.'
                : ($activeEnvironment instanceof ManagedEnvironment
                ? 'The landing is currently narrowed to one environment inside the active workspace.'
                : 'The landing is currently showing workspace-wide monitoring across all entitled environments.'),
            'return_label' => $returnLabel,
            'return_body' => $returnBody,
            'scope_reset_label' => $activeEnvironment instanceof ManagedEnvironment ? __('localization.shell.show_all_environments') : null,
            'scope_reset_body' => $activeEnvironment instanceof ManagedEnvironment
                ? 'Reset the landing back to workspace-wide monitoring when environment-specific context is no longer needed.'
                : null,
            'inspect_body' => 'Open a run from the table to enter the canonical monitoring detail viewer.',
        ];
    }

    public function tabUrl(string $tab): string
    {
        $normalizedTab = in_array($tab, self::supportedTabs(), true) ? $tab : 'all';

        return $this->operationsUrl([
            'activeTab' => $normalizedTab !== 'all' ? $normalizedTab : null,
            'problemClass' => in_array($normalizedTab, self::problemClassTabs(), true) ? $normalizedTab : null,
        ]);
    }

    /**
     * @return array{label: string, clear_url: string}|null
     */
    public function environmentFilterChip(): ?array
    {
        $tenant = $this->filteredTenant();

        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return [
            'label' => (string) $tenant->name,
            'clear_url' => $this->cleanWorkspaceHubUrl(route('admin.operations.index', [
                'workspace' => app(WorkspaceContext::class)->currentWorkspace(request()),
            ])),
        ];
    }

    private function navigationContext(): ?CanonicalNavigationContext
    {
        if (! is_array($this->navigationContextPayload)) {
            return CanonicalNavigationContext::fromRequest(request());
        }

        return CanonicalNavigationContext::fromPayload($this->navigationContextPayload);
    }

    public function updatedActiveTab(): void
    {
        $this->resetPage();
    }

    public function table(Table $table): Table
    {
        return OperationRunResource::table($table)
            ->query(function (): Builder {
                $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());
                $tenantFilter = $this->currentTenantFilterId();
                $allowedTenantIds = $this->allowedTenantIdsForWorkspaceScope($workspaceId);

                $query = OperationRun::query()
                    ->with('user')
                    ->latest('id')
                    ->when(
                        $workspaceId,
                        fn (Builder $query): Builder => $query->where('workspace_id', (int) $workspaceId),
                    )
                    ->when(
                        ! $workspaceId,
                        fn (Builder $query): Builder => $query->whereRaw('1 = 0'),
                    )
                    ->when(
                        $workspaceId && $allowedTenantIds !== null,
                        function (Builder $query) use ($allowedTenantIds): Builder {
                            return $query->where(function (Builder $query) use ($allowedTenantIds): void {
                                $query->whereNull('managed_environment_id');

                                if ($allowedTenantIds !== []) {
                                    $query->orWhereIn('managed_environment_id', $allowedTenantIds);
                                }
                            });
                        },
                    )
                    ->when(
                        $tenantFilter !== null,
                        fn (Builder $query): Builder => $query->where('managed_environment_id', $tenantFilter),
                    );

                return $this->applyActiveTab($query);
            });
    }

    /**
     * @return array{likely_stale:int,reconciled:int}
     */
    public function lifecycleVisibilitySummary(): array
    {
        $baseQuery = $this->scopedSummaryQuery();

        if (! $baseQuery instanceof Builder) {
            return [
                'likely_stale' => 0,
                'reconciled' => 0,
            ];
        }

        $reconciled = (clone $baseQuery)
            ->whereNotNull('context->reconciliation->reconciled_at')
            ->count();

        $policy = app(OperationLifecyclePolicy::class);
        $likelyStale = (clone $baseQuery)
            ->likelyStale($policy)
            ->count();

        return [
            'likely_stale' => $likelyStale,
            'reconciled' => $reconciled,
        ];
    }

    private function applyActiveTab(Builder $query): Builder
    {
        return match ($this->activeTab) {
            'active' => $query->healthyActive(),
            OperationRun::PROBLEM_CLASS_ACTIVE_STALE_ATTENTION => $query->activeStaleAttention(),
            OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP => $query->terminalFollowUp(),
            'blocked' => $query->dashboardNeedsFollowUp(),
            'succeeded' => $query
                ->where('status', OperationRunStatus::Completed->value)
                ->where('outcome', OperationRunOutcome::Succeeded->value),
            'partial' => $query
                ->where('status', OperationRunStatus::Completed->value)
                ->where('outcome', OperationRunOutcome::PartiallySucceeded->value),
            'failed' => $query
                ->where('status', OperationRunStatus::Completed->value)
                ->where('outcome', OperationRunOutcome::Failed->value),
            default => $query,
        };
    }

    private function scopedSummaryQuery(): ?Builder
    {
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if (! $workspaceId) {
            return null;
        }

        $tenantFilter = $this->currentTenantFilterId();
        $allowedTenantIds = $this->allowedTenantIdsForWorkspaceScope($workspaceId);

        return OperationRun::query()
            ->where('workspace_id', (int) $workspaceId)
            ->when(
                $allowedTenantIds !== null,
                function (Builder $query) use ($allowedTenantIds): Builder {
                    return $query->where(function (Builder $query) use ($allowedTenantIds): void {
                        $query->whereNull('managed_environment_id');

                        if ($allowedTenantIds !== []) {
                            $query->orWhereIn('managed_environment_id', $allowedTenantIds);
                        }
                    });
                },
            )
            ->when(
                $tenantFilter !== null,
                fn (Builder $query): Builder => $query->where('managed_environment_id', $tenantFilter),
            );
    }

    private function applyRequestedDashboardPrefilter(): void
    {
        $workspace = app(WorkspaceContext::class)->currentWorkspace(request());

        if ($workspace instanceof Workspace) {
            $filter = WorkspaceHubEnvironmentFilter::fromRequest(request(), $workspace);

            if ($filter instanceof WorkspaceHubEnvironmentFilter) {
                $requestedTenantId = $this->normalizeEntitledTenantFilter($filter->environmentId());

                if ($requestedTenantId === null) {
                    abort(404);
                }

                $tenantId = (string) $requestedTenantId;
                $this->tableFilters['managed_environment_id']['value'] = $tenantId;
                $this->tableDeferredFilters['managed_environment_id']['value'] = $tenantId;
            }
        }

        $requestedProblemClass = request()->query('problemClass');

        if (in_array($requestedProblemClass, self::problemClassTabs(), true)) {
            $this->activeTab = (string) $requestedProblemClass;

            return;
        }

        $requestedTab = request()->query('activeTab');

        if (in_array($requestedTab, self::supportedTabs(), true)) {
            $this->activeTab = (string) $requestedTab;
        }
    }

    private function operationsUrl(array $overrides = []): string
    {
        $parameters = array_merge(
            ['workspace' => app(WorkspaceContext::class)->currentWorkspace(request())],
            $this->navigationContext()?->toQuery() ?? [],
            [
                'environment_id' => $this->currentTenantFilterId(),
                'activeTab' => $this->activeTab !== 'all' ? $this->activeTab : null,
                'problemClass' => in_array($this->activeTab, self::problemClassTabs(), true) ? $this->activeTab : null,
            ],
            $overrides,
        );

        return route(
            'admin.operations.index',
            array_filter($parameters, static fn (mixed $value): bool => $value !== null && $value !== '' && $value !== []),
        );
    }

    private function currentTenantFilterId(): ?int
    {
        $tenantFilter = app(CanonicalAdminEnvironmentFilterState::class)->currentFilterValue(
            $this->getTableFiltersSessionKey(),
            $this->tableFilters ?? [],
            request(),
        );

        return $this->normalizeEntitledTenantFilter($tenantFilter);
    }

    private function filteredTenant(): ?ManagedEnvironment
    {
        $tenantId = $this->currentTenantFilterId();

        if (! is_int($tenantId)) {
            return null;
        }

        foreach ($this->authorizedTenants() as $tenant) {
            if ((int) $tenant->getKey() === $tenantId) {
                return $tenant;
            }
        }

        return null;
    }

    /**
     * Null means inherited access to all environments in the workspace.
     *
     * @return list<int>|null
     */
    private function allowedTenantIdsForWorkspaceScope(mixed $workspaceId): ?array
    {
        $user = auth()->user();

        if (! $user instanceof User || ! is_int($workspaceId)) {
            return [];
        }

        $allowedIds = app(ManagedEnvironmentAccessScopeResolver::class)
            ->allowedManagedEnvironmentIdsForWorkspace($user, $workspaceId);

        if ($allowedIds === null) {
            return null;
        }

        return array_values(array_unique(array_map('intval', $allowedIds)));
    }

    private function normalizeEntitledTenantFilter(mixed $value): ?int
    {
        if (! is_numeric($value)) {
            return null;
        }

        $tenantId = (int) $value;

        return in_array($tenantId, $this->authorizedTenantIds(), true)
            ? $tenantId
            : null;
    }

    /**
     * @return list<int>
     */
    private function authorizedTenantIds(): array
    {
        $user = auth()->user();
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if (! $user instanceof User || ! is_int($workspaceId)) {
            return [];
        }

        return collect($user->getTenants(Filament::getCurrentOrDefaultPanel()))
            ->filter(static fn (ManagedEnvironment $tenant): bool => (int) $tenant->workspace_id === $workspaceId)
            ->filter(static fn (ManagedEnvironment $tenant): bool => $tenant->isActive())
            ->map(static fn (ManagedEnvironment $tenant): int => (int) $tenant->getKey())
            ->values()
            ->all();
    }

    /**
     * @return array<int, ManagedEnvironment>
     */
    private function authorizedTenants(): array
    {
        $user = auth()->user();
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if (! $user instanceof User || ! is_int($workspaceId)) {
            return [];
        }

        return collect($user->getTenants(Filament::getCurrentOrDefaultPanel()))
            ->filter(static fn (ManagedEnvironment $tenant): bool => (int) $tenant->workspace_id === $workspaceId)
            ->filter(static fn (ManagedEnvironment $tenant): bool => $tenant->isActive())
            ->values()
            ->all();
    }

    /**
     * @return list<string>
     */
    private static function supportedTabs(): array
    {
        return [
            'all',
            'active',
            'blocked',
            'succeeded',
            'partial',
            'failed',
            ...self::problemClassTabs(),
        ];
    }

    /**
     * @return list<string>
     */
    private static function problemClassTabs(): array
    {
        return [
            OperationRun::PROBLEM_CLASS_ACTIVE_STALE_ATTENTION,
            OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP,
        ];
    }
}
