<?php

declare(strict_types=1);

namespace App\Filament\System\Pages\Ops;

use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Support\Auth\PlatformCapabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\OperationCatalog;
use App\Support\OperationRunStatus;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\System\SystemOperationRunLinks;
use App\Support\SystemConsole\StuckRunClassifier;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
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 Filament\Actions\Action;
use Filament\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class Stuck extends Page implements HasTable
{
    use InteractsWithTable;

    protected static ?string $navigationLabel = 'Stuck operations';

    protected static ?string $title = 'Stuck operations';

    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-clock';

    protected static string|\UnitEnum|null $navigationGroup = 'Ops';

    protected static ?string $slug = 'ops/stuck';

    protected string $view = 'filament.system.pages.ops.stuck';

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forPage(ActionSurfaceProfile::RunLog, ActionSurfaceType::ReadOnlyRegistryReport)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'The page header exposes Show all operations while row clicks remain the only inspect model.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Stuck operations remain scan-first and intentionally omit bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'The empty state explains when no operations cross the stuck thresholds and repeats the Show all operations CTA.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'Row navigation opens the canonical system run detail page, which owns header actions.');
    }

    public static function getNavigationBadge(): ?string
    {
        $count = app(StuckRunClassifier::class)
            ->apply(OperationRun::query())
            ->count();

        return $count > 0 ? (string) $count : null;
    }

    public static function getNavigationBadgeColor(): string|array|null
    {
        return 'warning';
    }

    public static function canAccess(): bool
    {
        $user = auth('platform')->user();

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

        return $user->hasCapability(PlatformCapabilities::OPERATIONS_VIEW)
            || ($user->hasCapability(PlatformCapabilities::OPS_VIEW) && $user->hasCapability(PlatformCapabilities::RUNBOOKS_VIEW));
    }

    public function mount(): void
    {
        $this->mountInteractsWithTable();
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        return [
            Action::make('show_all_operations')
                ->label('Show all operations')
                ->url(SystemOperationRunLinks::index()),
        ];
    }

    public function table(Table $table): Table
    {
        return $table
            ->defaultSort('id', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::customPage())
            ->query(function (): Builder {
                return app(StuckRunClassifier::class)->apply(
                    OperationRun::query()
                        ->with(['tenant', 'workspace'])
                );
            })
            ->columns([
                TextColumn::make('id')
                    ->label('ID')
                    ->state(fn (OperationRun $record): string => '#'.$record->getKey()),
                TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(fn (mixed $state, OperationRun $record): string => BadgeRenderer::spec(BadgeDomain::OperationRunStatus, [
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->label)
                    ->color(fn (mixed $state, OperationRun $record): string => BadgeRenderer::spec(BadgeDomain::OperationRunStatus, [
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->color)
                    ->icon(fn (mixed $state, OperationRun $record): ?string => BadgeRenderer::spec(BadgeDomain::OperationRunStatus, [
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->icon)
                    ->iconColor(fn (mixed $state, OperationRun $record): ?string => BadgeRenderer::spec(BadgeDomain::OperationRunStatus, [
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->iconColor)
                    ->description(null),
                TextColumn::make('stuck_class')
                    ->label('Stuck class')
                    ->state(function (OperationRun $record): string {
                        $classification = app(StuckRunClassifier::class)->classify($record);

                        return $classification === OperationRunStatus::Queued->value ? 'Queued too long' : 'Running too long';
                    }),
                TextColumn::make('type')
                    ->label('Operation')
                    ->formatStateUsing(fn (?string $state): string => OperationCatalog::label((string) $state))
                    ->description(fn (OperationRun $record): ?string => OperationUxPresenter::lifecycleAttentionSummary($record))
                    ->searchable(),
                TextColumn::make('workspace.name')
                    ->label('Workspace')
                    ->toggleable(),
                TextColumn::make('tenant.name')
                    ->label('Tenant')
                    ->formatStateUsing(fn (?string $state): string => $state ?: 'Tenantless')
                    ->toggleable(),
                TextColumn::make('created_at')->label('Started')->since(),
            ])
            ->recordUrl(fn (OperationRun $record): string => SystemOperationRunLinks::view($record))
            ->actions([])
            ->emptyStateHeading('No stuck operations found')
            ->emptyStateDescription('Queued and running operations that exceed the thresholds will appear here.')
            ->emptyStateActions([
                Action::make('show_all_operations_empty')
                    ->label('Show all operations')
                    ->url(SystemOperationRunLinks::index())
                    ->button(),
            ])
            ->bulkActions([]);
    }
}
