<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Clusters\Monitoring\AlertsCluster;
use App\Filament\Resources\AlertDeliveryResource\Pages;
use App\Models\AlertDelivery;
use App\Models\AlertDestination;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Auth\ManagedEnvironmentAccessScopeResolver;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\FilterPresets;
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 App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use UnitEnum;

class AlertDeliveryResource extends Resource
{
    protected static bool $isScopedToTenant = false;

    protected static ?string $model = AlertDelivery::class;

    protected static ?string $slug = 'alert-deliveries';

    protected static ?string $cluster = AlertsCluster::class;

    protected static ?int $navigationSort = 1;

    protected static bool $isGloballySearchable = false;

    protected static ?string $recordTitleAttribute = 'id';

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

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

    protected static ?string $navigationLabel = 'Alert deliveries';

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

        return parent::shouldRegisterNavigation();
    }

    public static function canViewAny(): bool
    {
        $user = auth()->user();

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

        return $user->can('viewAny', AlertDelivery::class);
    }

    public static function canView(Model $record): bool
    {
        $user = auth()->user();

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

        return $user->can('view', $record);
    }

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::ListOnlyReadOnly, ActionSurfaceType::ReadOnlyRegistryReport)
            ->exempt(ActionSurfaceSlot::ListHeader, 'Read-only history list intentionally has no list-header actions.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'No secondary row actions are exposed for read-only deliveries.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'No bulk actions are exposed for read-only deliveries.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'Guided empty state links to View alert rules.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'View page is informational with no mutating header actions.');
    }

    public static function makeViewAlertRulesAction(): Action
    {
        return Action::make('view_alert_rules')
            ->label('View alert rules')
            ->icon('heroicon-o-funnel')
            ->color('primary')
            ->button()
            ->url(AlertRuleResource::getUrl(panel: 'admin'));
    }

    public static function getEloquentQuery(): Builder
    {
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());
        $user = auth()->user();

        $scopeResolver = app(ManagedEnvironmentAccessScopeResolver::class);

        return parent::getEloquentQuery()
            ->with(['tenant', 'rule', 'destination'])
            ->when(
                ! $user instanceof User,
                fn (Builder $query): Builder => $query->whereRaw('1 = 0'),
            )
            ->when(
                ! is_int($workspaceId),
                fn (Builder $query): Builder => $query->whereRaw('1 = 0'),
            )
            ->when(
                is_int($workspaceId),
                fn (Builder $query): Builder => $query->where('workspace_id', $workspaceId),
            )
            ->when(
                $user instanceof User,
                fn (Builder $query): Builder => $query->where(function (Builder $q) use ($scopeResolver, $user, $workspaceId): void {
                    $q->whereNull('managed_environment_id')
                        ->orWhere(function (Builder $scopedQuery) use ($scopeResolver, $user, $workspaceId): void {
                            if (! is_int($workspaceId)) {
                                $scopedQuery->whereRaw('1 = 0');

                                return;
                            }

                            $scopeResolver->applyWorkspaceScopeToQuery(
                                query: $scopedQuery,
                                user: $user,
                                workspaceId: $workspaceId,
                                qualifiedEnvironmentColumn: 'alert_deliveries.managed_environment_id',
                            );
                        });
                }),
            )
            ->latest('id');
    }

    public static function form(Schema $schema): Schema
    {
        return $schema;
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('Delivery')
                    ->schema([
                        TextEntry::make('status')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::AlertDeliveryStatus))
                            ->color(BadgeRenderer::color(BadgeDomain::AlertDeliveryStatus))
                            ->icon(BadgeRenderer::icon(BadgeDomain::AlertDeliveryStatus)),
                        TextEntry::make('event_type')
                            ->label('Event')
                            ->badge()
                            ->formatStateUsing(fn (?string $state): string => AlertRuleResource::eventTypeLabel((string) $state)),
                        TextEntry::make('severity')
                            ->badge()
                            ->formatStateUsing(fn (?string $state): string => ucfirst((string) $state))
                            ->placeholder('—'),
                        TextEntry::make('tenant.name')
                            ->label('ManagedEnvironment'),
                        TextEntry::make('rule.name')
                            ->label('Rule')
                            ->placeholder('—'),
                        TextEntry::make('destination.name')
                            ->label('Destination')
                            ->placeholder('—'),
                        TextEntry::make('attempt_count')
                            ->label('Attempts'),
                        TextEntry::make('fingerprint_hash')
                            ->label('Fingerprint')
                            ->copyable(),
                        TextEntry::make('send_after')
                            ->dateTime()
                            ->placeholder('—'),
                        TextEntry::make('sent_at')
                            ->dateTime()
                            ->placeholder('—'),
                        TextEntry::make('last_error_code')
                            ->label('Last error code')
                            ->placeholder('—'),
                        TextEntry::make('last_error_message')
                            ->label('Last error message')
                            ->placeholder('—')
                            ->columnSpanFull(),
                        TextEntry::make('created_at')
                            ->dateTime(),
                        TextEntry::make('updated_at')
                            ->dateTime(),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),
                Section::make('Payload')
                    ->schema([
                        ViewEntry::make('payload')
                            ->label('')
                            ->view('filament.infolists.entries.snapshot-json')
                            ->state(fn (AlertDelivery $record): array => is_array($record->payload) ? $record->payload : [])
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('id', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::resource())
            ->persistFiltersInSession()
            ->persistSearchInSession()
            ->persistSortInSession()
            ->recordUrl(fn (AlertDelivery $record): ?string => static::canView($record)
                ? static::getUrl('view', ['record' => $record])
                : null)
            ->columns([
                TextColumn::make('created_at')
                    ->label('Created')
                    ->since()
                    ->sortable(),
                TextColumn::make('tenant.name')
                    ->label('ManagedEnvironment')
                    ->searchable(),
                TextColumn::make('event_type')
                    ->label('Event')
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => AlertRuleResource::eventTypeLabel((string) $state)),
                TextColumn::make('severity')
                    ->badge()
                    ->formatStateUsing(fn (?string $state): string => ucfirst((string) $state))
                    ->placeholder('—'),
                TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::AlertDeliveryStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::AlertDeliveryStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::AlertDeliveryStatus))
                    ->sortable(),
                TextColumn::make('rule.name')
                    ->label('Rule')
                    ->placeholder('—'),
                TextColumn::make('destination.name')
                    ->label('Destination')
                    ->placeholder('—'),
                TextColumn::make('attempt_count')
                    ->label('Attempts')
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                SelectFilter::make('managed_environment_id')
                    ->label('ManagedEnvironment')
                    ->options(function (): array {
                        $user = auth()->user();

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

                        return collect($user->getTenants(Filament::getCurrentOrDefaultPanel()))
                            ->mapWithKeys(static fn (ManagedEnvironment $tenant): array => [
                                (string) $tenant->getKey() => $tenant->getFilamentName(),
                            ])
                            ->all();
                    })
                    ->default(null)
                    ->searchable(),
                SelectFilter::make('status')
                    ->options(FilterOptionCatalog::alertDeliveryStatuses()),
                SelectFilter::make('event_type')
                    ->label('Event type')
                    ->options(function (): array {
                        $options = AlertRuleResource::eventTypeOptions();
                        $options[AlertDelivery::EVENT_TYPE_TEST] = 'Test';

                        return $options;
                    }),
                SelectFilter::make('alert_destination_id')
                    ->label('Destination')
                    ->options(function (): array {
                        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

                        if (! is_int($workspaceId)) {
                            return [];
                        }

                        return AlertDestination::query()
                            ->where('workspace_id', $workspaceId)
                            ->orderBy('name')
                            ->pluck('name', 'id')
                            ->all();
                    }),
                FilterPresets::dateRange('created_at', 'Created', 'created_at'),
            ])
            ->actions([])
            ->bulkActions([])
            ->emptyStateHeading('No alert deliveries')
            ->emptyStateDescription('Deliveries appear automatically when alert rules fire.')
            ->emptyStateIcon('heroicon-o-bell-alert')
            ->emptyStateActions([
                static::makeViewAlertRulesAction(),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListAlertDeliveries::route('/'),
            'view' => Pages\ViewAlertDelivery::route('/{record}'),
        ];
    }
}
