<?php

namespace App\Filament\Resources;

use App\Filament\Resources\PolicyVersionResource\Pages;
use App\Jobs\BulkPolicyVersionForceDeleteJob;
use App\Jobs\BulkPolicyVersionPruneJob;
use App\Jobs\BulkPolicyVersionRestoreJob;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\PolicyVersion;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Services\Intune\AuditLogger;
use App\Services\Intune\PolicyNormalizer;
use App\Services\Intune\VersionDiff;
use App\Services\OperationRunService;
use App\Services\Operations\BulkSelectionIdentity;
use App\Support\Auth\Capabilities;
use App\Support\Badges\TagBadgeDomain;
use App\Support\Badges\TagBadgeRenderer;
use App\Support\Baselines\PolicyVersionCapturePurpose;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\FilterPresets;
use App\Support\Navigation\CrossResourceNavigationMatrix;
use App\Support\Navigation\RelatedContextEntry;
use App\Support\Navigation\RelatedNavigationResolver;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\Rbac\UiEnforcement;
use App\Support\RedactionIntegrity;
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 BackedEnum;
use Carbon\CarbonImmutable;
use Filament\Actions;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Forms;
use Filament\Infolists;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use UnitEnum;

class PolicyVersionResource extends Resource
{
    protected static ?string $model = PolicyVersion::class;

    protected static ?string $tenantOwnershipRelationshipName = 'tenant';

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

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

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

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

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

        return $resolver->isMember($user, $tenant)
            && $resolver->can($user, $tenant, Capabilities::TENANT_VIEW);
    }

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::CrudListAndView)
            ->exempt(ActionSurfaceSlot::ListHeader, 'Policy versions list intentionally has no header actions; versions are created by sync and captures.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Secondary row actions are grouped under "More".')
            ->satisfy(ActionSurfaceSlot::ListBulkMoreGroup, 'Bulk actions are grouped under "More".')
            ->exempt(ActionSurfaceSlot::ListEmptyState, 'Empty-state CTA is intentionally omitted; versions appear after policy sync/capture workflows.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'View page header actions are intentionally minimal for now.');
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Infolists\Components\TextEntry::make('policy.display_name')
                    ->label('Policy')
                    ->state(fn (PolicyVersion $record): string => static::resolvedDisplayName($record)),
                Infolists\Components\TextEntry::make('version_number')->label('Version'),
                Infolists\Components\TextEntry::make('policy_type')
                    ->badge()
                    ->formatStateUsing(TagBadgeRenderer::label(TagBadgeDomain::PolicyType))
                    ->color(TagBadgeRenderer::color(TagBadgeDomain::PolicyType)),
                Infolists\Components\TextEntry::make('platform')
                    ->badge()
                    ->formatStateUsing(TagBadgeRenderer::label(TagBadgeDomain::Platform))
                    ->color(TagBadgeRenderer::color(TagBadgeDomain::Platform)),
                Infolists\Components\TextEntry::make('created_by')->label('Actor'),
                Infolists\Components\TextEntry::make('captured_at')->dateTime(),
                Section::make('Related context')
                    ->schema([
                        Infolists\Components\ViewEntry::make('related_context')
                            ->label('')
                            ->view('filament.infolists.entries.related-context')
                            ->state(fn (PolicyVersion $record): array => static::relatedContextEntries($record))
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
                Tabs::make()
                    ->activeTab(1)
                    ->persistTabInQueryString('tab')
                    ->columnSpanFull()
                    ->tabs([
                        Tab::make('Normalized settings')
                            ->id('normalized-settings')
                            ->schema([
                                Infolists\Components\ViewEntry::make('normalized_settings_catalog')
                                    ->view('filament.infolists.entries.normalized-settings')
                                    ->state(function (PolicyVersion $record) {
                                        $normalized = app(PolicyNormalizer::class)->normalize(
                                            is_array($record->snapshot) ? $record->snapshot : [],
                                            $record->policy_type ?? '',
                                            $record->platform
                                        );

                                        $normalized['context'] = 'version';
                                        $normalized['record_id'] = (string) $record->getKey();

                                        return $normalized;
                                    })
                                    ->visible(fn (PolicyVersion $record) => in_array($record->policy_type, ['settingsCatalogPolicy', 'endpointSecurityPolicy', 'securityBaselinePolicy'], true)),

                                Infolists\Components\ViewEntry::make('normalized_settings_standard')
                                    ->view('filament.infolists.entries.policy-settings-standard')
                                    ->state(function (PolicyVersion $record) {
                                        $normalized = app(PolicyNormalizer::class)->normalize(
                                            is_array($record->snapshot) ? $record->snapshot : [],
                                            $record->policy_type ?? '',
                                            $record->platform
                                        );

                                        $normalized['context'] = 'version';
                                        $normalized['record_id'] = (string) $record->getKey();
                                        $normalized['policy_type'] = $record->policy_type;

                                        return $normalized;
                                    })
                                    ->visible(fn (PolicyVersion $record) => ! in_array($record->policy_type, ['settingsCatalogPolicy', 'endpointSecurityPolicy', 'securityBaselinePolicy'], true)),
                            ]),
                        Tab::make('Raw JSON')
                            ->id('raw-json')
                            ->schema([
                                Infolists\Components\ViewEntry::make('snapshot_pretty')
                                    ->view('filament.infolists.entries.snapshot-json')
                                    ->state(fn (PolicyVersion $record) => $record->snapshot ?? []),
                            ]),
                        Tab::make('Diff')
                            ->id('diff')
                            ->schema([
                                Infolists\Components\ViewEntry::make('normalized_diff')
                                    ->view('filament.infolists.entries.normalized-diff')
                                    ->state(function (PolicyVersion $record) {
                                        $normalizer = app(PolicyNormalizer::class);
                                        $diff = app(VersionDiff::class);

                                        $previous = $record->previous();
                                        $from = $previous
                                            ? $normalizer->flattenForDiff($previous->snapshot ?? [], $previous->policy_type ?? '', $previous->platform)
                                            : [];
                                        $to = $normalizer->flattenForDiff($record->snapshot ?? [], $record->policy_type ?? '', $record->platform);

                                        $result = $diff->compare($from, $to);
                                        $result['policy_type'] = $record->policy_type;

                                        return $result;
                                    }),
                                Infolists\Components\ViewEntry::make('diff_json')
                                    ->label('Raw diff (advanced)')
                                    ->view('filament.infolists.entries.snapshot-json')
                                    ->state(function (PolicyVersion $record) {
                                        $previous = $record->previous();

                                        if (! $previous) {
                                            return ['summary' => 'No previous version'];
                                        }

                                        $diff = app(VersionDiff::class)->compare(
                                            $previous->snapshot ?? [],
                                            $record->snapshot ?? []
                                        );

                                        $filter = static fn (array $items): array => array_filter(
                                            $items,
                                            static fn (mixed $value, string $key): bool => ! str_contains($key, '@odata.context'),
                                            ARRAY_FILTER_USE_BOTH
                                        );

                                        $added = $filter($diff['added'] ?? []);
                                        $removed = $filter($diff['removed'] ?? []);
                                        $changed = $filter($diff['changed'] ?? []);

                                        return [
                                            'summary' => [
                                                'added' => count($added),
                                                'removed' => count($removed),
                                                'changed' => count($changed),
                                                'message' => sprintf(
                                                    '%d added, %d removed, %d changed',
                                                    count($added),
                                                    count($removed),
                                                    count($changed)
                                                ),
                                            ],
                                            'added' => $added,
                                            'removed' => $removed,
                                            'changed' => $changed,
                                        ];
                                    }),
                            ]),
                    ]),
            ]);
    }

    public static function table(Table $table): Table
    {
        $bulkPruneVersions = BulkAction::make('bulk_prune_versions')
            ->label('Prune Versions')
            ->icon('heroicon-o-trash')
            ->color('danger')
            ->requiresConfirmation()
            ->modalDescription('Only versions captured more than the specified retention window (in days) are eligible. Newer versions will be skipped.')
            ->hidden(function (HasTable $livewire): bool {
                $trashedFilterState = $livewire->getTableFilterState(TrashedFilter::class) ?? [];
                $value = $trashedFilterState['value'] ?? null;

                $isOnlyTrashed = in_array($value, [0, '0', false], true);

                return $isOnlyTrashed;
            })
            ->form(function (Collection $records) {
                $fields = [
                    Forms\Components\TextInput::make('retention_days')
                        ->label('Retention Days')
                        ->helperText('Versions captured within the last N days will be skipped.')
                        ->numeric()
                        ->required()
                        ->default(90)
                        ->minValue(1),
                ];

                if ($records->count() >= 20) {
                    $fields[] = Forms\Components\TextInput::make('confirmation')
                        ->label('Type DELETE to confirm')
                        ->required()
                        ->in(['DELETE'])
                        ->validationMessages([
                            'in' => 'Please type DELETE to confirm.',
                        ]);
                }

                return $fields;
            })
            ->action(function (Collection $records, array $data) {
                $tenant = Tenant::current();
                $user = auth()->user();
                $count = $records->count();
                $ids = $records->pluck('id')->toArray();

                $retentionDays = (int) ($data['retention_days'] ?? 90);

                if (! $tenant instanceof Tenant) {
                    return;
                }

                if (! $user instanceof User) {
                    abort(403);
                }

                $initiator = $user;

                /** @var BulkSelectionIdentity $selection */
                $selection = app(BulkSelectionIdentity::class);
                $selectionIdentity = $selection->fromIds($ids);

                /** @var OperationRunService $runs */
                $runs = app(OperationRunService::class);

                $opRun = $runs->enqueueBulkOperation(
                    tenant: $tenant,
                    type: 'policy_version.prune',
                    targetScope: [
                        'entra_tenant_id' => (string) ($tenant->tenant_id ?? $tenant->external_id),
                    ],
                    selectionIdentity: $selectionIdentity,
                    dispatcher: function ($operationRun) use ($tenant, $initiator, $ids, $retentionDays): void {
                        BulkPolicyVersionPruneJob::dispatch(
                            tenantId: (int) $tenant->getKey(),
                            userId: (int) $initiator->getKey(),
                            policyVersionIds: $ids,
                            retentionDays: $retentionDays,
                            operationRun: $operationRun,
                        );
                    },
                    initiator: $initiator,
                    extraContext: [
                        'policy_version_count' => $count,
                        'retention_days' => $retentionDays,
                    ],
                    emitQueuedNotification: false,
                );

                OperationUxPresenter::queuedToast('policy_version.prune')
                    ->actions([
                        Actions\Action::make('view_run')
                            ->label('View run')
                            ->url(OperationRunLinks::view($opRun, $tenant)),
                    ])
                    ->send();
            })
            ->deselectRecordsAfterCompletion();

        UiEnforcement::forBulkAction($bulkPruneVersions)
            ->requireCapability(Capabilities::TENANT_MANAGE)
            ->tooltip('You do not have permission to manage policy versions.')
            ->apply();

        $bulkRestoreVersions = BulkAction::make('bulk_restore_versions')
            ->label('Restore Versions')
            ->icon('heroicon-o-arrow-uturn-left')
            ->color('success')
            ->requiresConfirmation()
            ->hidden(function (HasTable $livewire): bool {
                $trashedFilterState = $livewire->getTableFilterState(TrashedFilter::class) ?? [];
                $value = $trashedFilterState['value'] ?? null;

                $isOnlyTrashed = in_array($value, [0, '0', false], true);

                return ! $isOnlyTrashed;
            })
            ->modalHeading(fn (Collection $records) => "Restore {$records->count()} policy versions?")
            ->modalDescription('Archived versions will be restored back to the active list. Active versions will be skipped.')
            ->action(function (Collection $records) {
                $tenant = Tenant::current();
                $user = auth()->user();
                $count = $records->count();
                $ids = $records->pluck('id')->toArray();

                if (! $tenant instanceof Tenant) {
                    return;
                }

                if (! $user instanceof User) {
                    abort(403);
                }

                $initiator = $user;

                /** @var BulkSelectionIdentity $selection */
                $selection = app(BulkSelectionIdentity::class);
                $selectionIdentity = $selection->fromIds($ids);

                /** @var OperationRunService $runs */
                $runs = app(OperationRunService::class);

                $opRun = $runs->enqueueBulkOperation(
                    tenant: $tenant,
                    type: 'policy_version.restore',
                    targetScope: [
                        'entra_tenant_id' => (string) ($tenant->tenant_id ?? $tenant->external_id),
                    ],
                    selectionIdentity: $selectionIdentity,
                    dispatcher: function ($operationRun) use ($tenant, $initiator, $ids): void {
                        BulkPolicyVersionRestoreJob::dispatch(
                            tenantId: (int) $tenant->getKey(),
                            userId: (int) $initiator->getKey(),
                            policyVersionIds: $ids,
                            operationRun: $operationRun,
                        );
                    },
                    initiator: $initiator,
                    extraContext: [
                        'policy_version_count' => $count,
                    ],
                    emitQueuedNotification: false,
                );

                OperationUxPresenter::queuedToast('policy_version.restore')
                    ->actions([
                        Actions\Action::make('view_run')
                            ->label('View run')
                            ->url(OperationRunLinks::view($opRun, $tenant)),
                    ])
                    ->send();
            })
            ->deselectRecordsAfterCompletion();

        UiEnforcement::forBulkAction($bulkRestoreVersions)
            ->requireCapability(Capabilities::TENANT_MANAGE)
            ->tooltip('You do not have permission to manage policy versions.')
            ->apply();

        $bulkForceDeleteVersions = BulkAction::make('bulk_force_delete_versions')
            ->label('Force Delete Versions')
            ->icon('heroicon-o-trash')
            ->color('danger')
            ->requiresConfirmation()
            ->hidden(function (HasTable $livewire): bool {
                $trashedFilterState = $livewire->getTableFilterState(TrashedFilter::class) ?? [];
                $value = $trashedFilterState['value'] ?? null;

                $isOnlyTrashed = in_array($value, [0, '0', false], true);

                return ! $isOnlyTrashed;
            })
            ->modalHeading(fn (Collection $records) => "Force delete {$records->count()} policy versions?")
            ->modalDescription('This is permanent. Only archived versions will be permanently deleted; active versions will be skipped.')
            ->form([
                Forms\Components\TextInput::make('confirmation')
                    ->label('Type DELETE to confirm')
                    ->required()
                    ->in(['DELETE'])
                    ->validationMessages([
                        'in' => 'Please type DELETE to confirm.',
                    ]),
            ])
            ->action(function (Collection $records, array $data) {
                $tenant = Tenant::current();
                $user = auth()->user();
                $count = $records->count();
                $ids = $records->pluck('id')->toArray();

                if (! $tenant instanceof Tenant) {
                    return;
                }

                if (! $user instanceof User) {
                    abort(403);
                }

                $initiator = $user;

                /** @var BulkSelectionIdentity $selection */
                $selection = app(BulkSelectionIdentity::class);
                $selectionIdentity = $selection->fromIds($ids);

                /** @var OperationRunService $runs */
                $runs = app(OperationRunService::class);

                $opRun = $runs->enqueueBulkOperation(
                    tenant: $tenant,
                    type: 'policy_version.force_delete',
                    targetScope: [
                        'entra_tenant_id' => (string) ($tenant->tenant_id ?? $tenant->external_id),
                    ],
                    selectionIdentity: $selectionIdentity,
                    dispatcher: function ($operationRun) use ($tenant, $initiator, $ids): void {
                        BulkPolicyVersionForceDeleteJob::dispatch(
                            tenantId: (int) $tenant->getKey(),
                            userId: (int) $initiator->getKey(),
                            policyVersionIds: $ids,
                            operationRun: $operationRun,
                        );
                    },
                    initiator: $initiator,
                    extraContext: [
                        'policy_version_count' => $count,
                    ],
                    emitQueuedNotification: false,
                );

                OperationUxPresenter::queuedToast('policy_version.force_delete')
                    ->actions([
                        Actions\Action::make('view_run')
                            ->label('View run')
                            ->url(OperationRunLinks::view($opRun, $tenant)),
                    ])
                    ->send();
            })
            ->deselectRecordsAfterCompletion();

        UiEnforcement::forBulkAction($bulkForceDeleteVersions)
            ->requireCapability(Capabilities::TENANT_MANAGE)
            ->tooltip('You do not have permission to manage policy versions.')
            ->apply();

        return $table
            ->defaultSort('captured_at', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::resource())
            ->persistFiltersInSession()
            ->persistSearchInSession()
            ->persistSortInSession()
            ->columns([
                Tables\Columns\TextColumn::make('policy.display_name')
                    ->label('Policy')
                    ->sortable()
                    ->searchable()
                    ->getStateUsing(fn (PolicyVersion $record): string => static::resolvedDisplayName($record)),
                Tables\Columns\TextColumn::make('version_number')->sortable(),
                Tables\Columns\TextColumn::make('policy_type')
                    ->badge()
                    ->formatStateUsing(TagBadgeRenderer::label(TagBadgeDomain::PolicyType))
                    ->color(TagBadgeRenderer::color(TagBadgeDomain::PolicyType)),
                Tables\Columns\TextColumn::make('platform')
                    ->badge()
                    ->formatStateUsing(TagBadgeRenderer::label(TagBadgeDomain::Platform))
                    ->color(TagBadgeRenderer::color(TagBadgeDomain::Platform)),
                Tables\Columns\TextColumn::make('created_by')->label('Actor'),
                Tables\Columns\TextColumn::make('captured_at')->dateTime()->sortable(),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('policy_type')
                    ->label('Type')
                    ->options(FilterOptionCatalog::policyTypes())
                    ->searchable(),
                Tables\Filters\SelectFilter::make('platform')
                    ->options(FilterOptionCatalog::platforms())
                    ->searchable(),
                FilterPresets::dateRange('captured_at', 'Captured', 'captured_at'),
                FilterPresets::archived(),
            ])
            ->recordUrl(static fn (PolicyVersion $record): ?string => static::canView($record)
                ? static::getUrl('view', ['record' => $record])
                : null)
            ->actions([
                static::primaryRelatedAction(),
                Actions\ActionGroup::make([
                    (function (): Actions\Action {
                        $action = Actions\Action::make('restore_via_wizard')
                            ->label('Restore via Wizard')
                            ->icon('heroicon-o-arrow-path-rounded-square')
                            ->color('primary')
                            ->requiresConfirmation()
                            ->modalHeading(fn (PolicyVersion $record): string => "Restore version {$record->version_number} via wizard?")
                            ->modalSubheading('Creates a 1-item backup set from this snapshot and opens the restore run wizard prefilled.')
                            ->visible(function (): bool {
                                $tenant = Tenant::current();
                                $user = auth()->user();

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

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

                                return $resolver->isMember($user, $tenant);
                            })
                            ->disabled(function (PolicyVersion $record): bool {
                                if (($record->metadata['source'] ?? null) === 'metadata_only') {
                                    return true;
                                }

                                $tenant = Tenant::current();
                                $user = auth()->user();

                                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                                    return true;
                                }

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

                                if (! $resolver->isMember($user, $tenant)) {
                                    return true;
                                }

                                return ! $resolver->can($user, $tenant, Capabilities::TENANT_MANAGE);
                            })
                            ->tooltip(function (PolicyVersion $record): ?string {
                                $tenant = Tenant::current();
                                $user = auth()->user();

                                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                                    return null;
                                }

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

                                if (! $resolver->isMember($user, $tenant)) {
                                    return null;
                                }

                                if (! $resolver->can($user, $tenant, Capabilities::TENANT_MANAGE)) {
                                    return 'You do not have permission to create restore runs.';
                                }

                                if (($record->metadata['source'] ?? null) === 'metadata_only') {
                                    return 'Disabled for metadata-only snapshots (Graph did not provide policy settings).';
                                }

                                return null;
                            })
                            ->action(function (PolicyVersion $record) {
                                $tenant = Tenant::current();
                                $user = auth()->user();

                                if (! $tenant instanceof Tenant || ! $user instanceof User) {
                                    abort(403);
                                }

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

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

                                if (! $resolver->can($user, $tenant, Capabilities::TENANT_MANAGE)) {
                                    abort(403);
                                }

                                if (($record->metadata['source'] ?? null) === 'metadata_only') {
                                    Notification::make()
                                        ->title('Restore disabled for metadata-only snapshot')
                                        ->body('This snapshot only contains metadata; Graph did not provide policy settings to restore.')
                                        ->warning()
                                        ->send();

                                    return;
                                }

                                if (! $tenant || $record->tenant_id !== $tenant->id) {
                                    Notification::make()
                                        ->title('Policy version belongs to a different tenant')
                                        ->danger()
                                        ->send();

                                    return;
                                }

                                $policy = $record->policy;

                                if (! $policy) {
                                    Notification::make()
                                        ->title('Policy could not be found for this version')
                                        ->danger()
                                        ->send();

                                    return;
                                }

                                $backupSet = BackupSet::create([
                                    'tenant_id' => $tenant->id,
                                    'name' => sprintf(
                                        'Policy Version Restore • %s • v%d',
                                        $policy->display_name,
                                        $record->version_number
                                    ),
                                    'created_by' => $user?->email,
                                    'status' => 'completed',
                                    'item_count' => 1,
                                    'completed_at' => CarbonImmutable::now(),
                                    'metadata' => [
                                        'source' => 'policy_version',
                                        'policy_version_id' => $record->id,
                                        'policy_version_number' => $record->version_number,
                                        'policy_id' => $policy->id,
                                        'redaction_version' => $record->redaction_version,
                                        'integrity_warning' => RedactionIntegrity::noteForPolicyVersion($record),
                                    ],
                                ]);

                                $scopeTags = is_array($record->scope_tags) ? $record->scope_tags : [];
                                $scopeTagIds = $scopeTags['ids'] ?? null;
                                $scopeTagNames = $scopeTags['names'] ?? null;

                                $backupItemMetadata = [
                                    'source' => 'policy_version',
                                    'display_name' => $policy->display_name,
                                    'policy_version_id' => $record->id,
                                    'policy_version_number' => $record->version_number,
                                    'version_captured_at' => $record->captured_at?->toIso8601String(),
                                    'redaction_version' => $record->redaction_version,
                                ];

                                $integrityWarning = RedactionIntegrity::noteForPolicyVersion($record);

                                if ($integrityWarning !== null) {
                                    $backupItemMetadata['integrity_warning'] = $integrityWarning;
                                }

                                $secretFingerprints = is_array($record->secret_fingerprints) ? $record->secret_fingerprints : [];
                                $protectedPathsCount = RedactionIntegrity::fingerprintCount($secretFingerprints);

                                if ($protectedPathsCount > 0) {
                                    $backupItemMetadata['protected_paths_count'] = $protectedPathsCount;
                                }

                                if (is_array($scopeTagIds) && $scopeTagIds !== []) {
                                    $backupItemMetadata['scope_tag_ids'] = $scopeTagIds;
                                }

                                if (is_array($scopeTagNames) && $scopeTagNames !== []) {
                                    $backupItemMetadata['scope_tag_names'] = $scopeTagNames;
                                }

                                $backupItem = BackupItem::create([
                                    'tenant_id' => $tenant->id,
                                    'backup_set_id' => $backupSet->id,
                                    'policy_id' => $policy->id,
                                    'policy_version_id' => $record->id,
                                    'policy_identifier' => $policy->external_id,
                                    'policy_type' => $policy->policy_type,
                                    'platform' => $policy->platform,
                                    'captured_at' => $record->captured_at ?? CarbonImmutable::now(),
                                    'payload' => $record->snapshot ?? [],
                                    'metadata' => $backupItemMetadata,
                                    'assignments' => $record->assignments,
                                ]);

                                return redirect()->to(RestoreRunResource::getUrl('create', [
                                    'backup_set_id' => $backupSet->id,
                                    'scope_mode' => 'selected',
                                    'backup_item_ids' => [$backupItem->id],
                                ]));
                            });

                        return $action;
                    })(),
                    (function (): Actions\Action {
                        $action = Actions\Action::make('archive')
                            ->label('Archive')
                            ->color('danger')
                            ->icon('heroicon-o-archive-box-x-mark')
                            ->requiresConfirmation()
                            ->visible(fn (PolicyVersion $record) => ! $record->trashed())
                            ->action(function (PolicyVersion $record, AuditLogger $auditLogger) {
                                $user = auth()->user();
                                $tenant = $record->tenant;

                                if (! $user instanceof User || ! $tenant instanceof Tenant) {
                                    abort(403);
                                }

                                $record->delete();

                                if ($record->tenant) {
                                    $auditLogger->log(
                                        tenant: $record->tenant,
                                        action: 'policy_version.deleted',
                                        resourceType: 'policy_version',
                                        resourceId: (string) $record->id,
                                        status: 'success',
                                        context: ['metadata' => ['policy_id' => $record->policy_id, 'version' => $record->version_number]]
                                    );
                                }

                                Notification::make()
                                    ->title('Policy version archived')
                                    ->success()
                                    ->send();
                            });

                        UiEnforcement::forAction($action)
                            ->preserveVisibility()
                            ->requireCapability(Capabilities::TENANT_MANAGE)
                            ->tooltip('You do not have permission to manage policy versions.')
                            ->apply();

                        return $action;
                    })(),
                    (function (): Actions\Action {
                        $action = Actions\Action::make('forceDelete')
                            ->label('Force delete')
                            ->color('danger')
                            ->icon('heroicon-o-trash')
                            ->requiresConfirmation()
                            ->visible(fn (PolicyVersion $record) => $record->trashed())
                            ->action(function (PolicyVersion $record, AuditLogger $auditLogger) {
                                $user = auth()->user();
                                $tenant = $record->tenant;

                                if (! $user instanceof User || ! $tenant instanceof Tenant) {
                                    abort(403);
                                }

                                if ($record->tenant) {
                                    $auditLogger->log(
                                        tenant: $record->tenant,
                                        action: 'policy_version.force_deleted',
                                        resourceType: 'policy_version',
                                        resourceId: (string) $record->id,
                                        status: 'success',
                                        context: ['metadata' => ['policy_id' => $record->policy_id, 'version' => $record->version_number]]
                                    );
                                }

                                $record->forceDelete();

                                Notification::make()
                                    ->title('Policy version permanently deleted')
                                    ->success()
                                    ->send();
                            });

                        UiEnforcement::forAction($action)
                            ->preserveVisibility()
                            ->requireCapability(Capabilities::TENANT_MANAGE)
                            ->tooltip('You do not have permission to manage policy versions.')
                            ->apply();

                        return $action;
                    })(),

                    (function (): Actions\Action {
                        $action = Actions\Action::make('restore')
                            ->label('Restore')
                            ->color('success')
                            ->icon('heroicon-o-arrow-uturn-left')
                            ->requiresConfirmation()
                            ->visible(fn (PolicyVersion $record) => $record->trashed())
                            ->action(function (PolicyVersion $record, AuditLogger $auditLogger) {
                                $user = auth()->user();
                                $tenant = $record->tenant;

                                if (! $user instanceof User || ! $tenant instanceof Tenant) {
                                    abort(403);
                                }

                                $record->restore();

                                if ($record->tenant) {
                                    $auditLogger->log(
                                        tenant: $record->tenant,
                                        action: 'policy_version.restored',
                                        resourceType: 'policy_version',
                                        resourceId: (string) $record->id,
                                        status: 'success',
                                        context: ['metadata' => ['policy_id' => $record->policy_id, 'version' => $record->version_number]]
                                    );
                                }

                                Notification::make()
                                    ->title('Policy version restored')
                                    ->success()
                                    ->send();
                            });

                        UiEnforcement::forAction($action)
                            ->preserveVisibility()
                            ->requireCapability(Capabilities::TENANT_MANAGE)
                            ->tooltip('You do not have permission to manage policy versions.')
                            ->apply();

                        return $action;
                    })(),
                ])
                    ->label('More')
                    ->icon('heroicon-o-ellipsis-vertical')
                    ->color('gray'),
            ])
            ->bulkActions([
                BulkActionGroup::make([
                    $bulkPruneVersions,
                    $bulkRestoreVersions,
                    $bulkForceDeleteVersions,
                ])->label('More'),
            ])
            ->emptyStateHeading('No policy versions')
            ->emptyStateDescription('Capture or sync policy snapshots to build a version history.')
            ->emptyStateIcon('heroicon-o-clock');
    }

    public static function getEloquentQuery(): Builder
    {
        $tenant = Tenant::currentOrFail();
        $tenantId = $tenant->getKey();
        $user = auth()->user();

        $resolver = app(CapabilityResolver::class);
        $canSeeBaselinePurposeEvidence = $user instanceof User
            && (
                $resolver->can($user, $tenant, Capabilities::TENANT_SYNC)
                || $resolver->can($user, $tenant, Capabilities::TENANT_FINDINGS_VIEW)
            );

        return parent::getEloquentQuery()
            ->when($tenantId, fn (Builder $query) => $query->where('tenant_id', $tenantId))
            ->when(! $canSeeBaselinePurposeEvidence, function (Builder $query): Builder {
                return $query->where(function (Builder $query): void {
                    $query
                        ->whereNull('capture_purpose')
                        ->orWhereNotIn('capture_purpose', [
                            PolicyVersionCapturePurpose::BaselineCapture->value,
                            PolicyVersionCapturePurpose::BaselineCompare->value,
                        ]);
                });
            })
            ->with('policy');
    }

    /**
     * @return list<array{
     *     key: string,
     *     label: string,
     *     value: string,
     *     secondaryValue: ?string,
     *     targetUrl: ?string,
     *     targetKind: string,
     *     availability: string,
     *     unavailableReason: ?string,
     *     contextBadge: ?string,
     *     priority: int,
     *     actionLabel: string
     * }>
     */
    public static function relatedContextEntries(PolicyVersion $record): array
    {
        return app(RelatedNavigationResolver::class)
            ->detailEntries(CrossResourceNavigationMatrix::SOURCE_POLICY_VERSION, $record);
    }

    private static function primaryRelatedAction(): Actions\Action
    {
        return Actions\Action::make('primary_drill_down')
            ->label(fn (PolicyVersion $record): string => static::primaryRelatedEntry($record)?->actionLabel ?? 'Open related record')
            ->url(fn (PolicyVersion $record): ?string => static::primaryRelatedEntry($record)?->targetUrl)
            ->hidden(fn (PolicyVersion $record): bool => ! (static::primaryRelatedEntry($record)?->isAvailable() ?? false))
            ->color('gray');
    }

    private static function primaryRelatedEntry(PolicyVersion $record): ?RelatedContextEntry
    {
        return app(RelatedNavigationResolver::class)
            ->primaryListAction(CrossResourceNavigationMatrix::SOURCE_POLICY_VERSION, $record);
    }

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

    private static function resolvedDisplayName(PolicyVersion $record): string
    {
        $snapshot = is_array($record->snapshot) ? $record->snapshot : [];
        $displayName = $snapshot['displayName']
            ?? $snapshot['name']
            ?? $record->policy?->display_name
            ?? null;

        if (is_string($displayName) && $displayName !== '') {
            return $displayName;
        }

        return sprintf('Version %d', (int) $record->version_number);
    }
}
