<?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\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\System\SystemOperationRunLinks;
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 Failures extends Page implements HasTable
{
    use InteractsWithTable;

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

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

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

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

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

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

    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, 'Failed operations remain scan-first and intentionally omit bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'The empty state explains when there are no failed operations 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 = OperationRun::query()
            ->where('status', OperationRunStatus::Completed->value)
            ->where('outcome', OperationRunOutcome::Failed->value)
            ->count();

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

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

    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 OperationRun::query()
                    ->with(['tenant', 'workspace'])
                    ->where('status', OperationRunStatus::Completed->value)
                    ->where('outcome', OperationRunOutcome::Failed->value);
            })
            ->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(fn (OperationRun $record): ?string => OperationUxPresenter::lifecycleAttentionSummary($record)),
                TextColumn::make('outcome')
                    ->badge()
                    ->formatStateUsing(fn (mixed $state, OperationRun $record): string => BadgeRenderer::spec(BadgeDomain::OperationRunOutcome, [
                        'outcome' => (string) $record->outcome,
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->label)
                    ->color(fn (mixed $state, OperationRun $record): string => BadgeRenderer::spec(BadgeDomain::OperationRunOutcome, [
                        'outcome' => (string) $record->outcome,
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->color)
                    ->icon(fn (mixed $state, OperationRun $record): ?string => BadgeRenderer::spec(BadgeDomain::OperationRunOutcome, [
                        'outcome' => (string) $record->outcome,
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->icon)
                    ->iconColor(fn (mixed $state, OperationRun $record): ?string => BadgeRenderer::spec(BadgeDomain::OperationRunOutcome, [
                        'outcome' => (string) $record->outcome,
                        'status' => (string) $record->status,
                        'freshness_state' => $record->freshnessState()->value,
                    ])->iconColor)
                    ->description(fn (OperationRun $record): ?string => OperationUxPresenter::surfaceGuidance($record)),
                TextColumn::make('type')
                    ->label('Operation')
                    ->formatStateUsing(fn (?string $state): string => OperationCatalog::label((string) $state))
                    ->searchable(),
                TextColumn::make('workspace.name')
                    ->label('Workspace')
                    ->toggleable(),
                TextColumn::make('tenant.name')
                    ->label('ManagedEnvironment')
                    ->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 failed operations found')
            ->emptyStateDescription('Failed operations will appear here when a run completes unsuccessfully.')
            ->emptyStateActions([
                Action::make('show_all_operations_empty')
                    ->label('Show all operations')
                    ->url(SystemOperationRunLinks::index())
                    ->button(),
            ])
            ->bulkActions([]);
    }
}
