<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EvidenceSnapshotResource\Pages;
use App\Models\EvidenceSnapshot;
use App\Models\EvidenceSnapshotItem;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Evidence\EvidenceSnapshotService;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\RelatedContextEntry;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Rbac\UiEnforcement;
use App\Support\Rbac\UiTooltips;
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\Ui\GovernanceActions\GovernanceActionCatalog;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use BackedEnum;
use Filament\Actions;
use Filament\Forms\Components\Textarea;
use Filament\Infolists\Components\RepeatableEntry;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
use Filament\Notifications\Notification;
use Filament\Panel;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Routing\Route;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Route as RouteFacade;
use Illuminate\Support\Str;
use UnitEnum;

class EvidenceSnapshotResource extends Resource
{
    use InteractsWithTenantOwnedRecords;
    use ResolvesPanelTenantContext;
    use WorkspaceScopedEnvironmentRoutes;

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

    protected static ?string $slug = 'evidence';

    protected static ?string $tenantOwnershipRelationshipName = 'tenant';

    protected static bool $isGloballySearchable = false;

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

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

    protected static ?string $navigationLabel = 'Evidence';

    protected static ?int $navigationSort = 55;

    public static function shouldRegisterNavigation(): bool
    {
        return NavigationScope::shouldRegisterEnvironmentNavigation()
            && parent::shouldRegisterNavigation();
    }

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

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

        if (! $user->canAccessTenant($tenant)) {
            return false;
        }

        return $user->can(Capabilities::EVIDENCE_VIEW, $tenant);
    }

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

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

        if (! $user->canAccessTenant($tenant) || ! $user->can(Capabilities::EVIDENCE_VIEW, $tenant)) {
            return false;
        }

        return ! $record instanceof EvidenceSnapshot
            || ((int) $record->managed_environment_id === (int) $tenant->getKey() && (int) $record->workspace_id === (int) $tenant->workspace_id);
    }

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::CrudListAndView, ActionSurfaceType::ReadOnlyRegistryReport)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Create snapshot is available from the list header.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'Empty state includes a Create snapshot CTA.')
            ->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Clickable-row inspection stays primary while Expire snapshot remains grouped under More.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Evidence snapshots do not support bulk actions.')
            ->satisfy(ActionSurfaceSlot::DetailHeader, 'View page exposes Refresh evidence as the primary action, keeps Expire snapshot visibly separated as danger, and renders operation/review-pack navigation in contextual related context.');
    }

    public static function getEloquentQuery(): Builder
    {
        return static::getTenantOwnedEloquentQuery()->with(['tenant', 'initiator', 'operationRun', 'items']);
    }

    public static function resolveScopedRecordOrFail(int|string|null $record): Model
    {
        return static::resolveTenantOwnedRecordOrFail($record);
    }

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

    public static function infolist(Schema $schema): Schema
    {
        return $schema->schema([
            Section::make('Outcome summary')
                ->schema([
                    ViewEntry::make('artifact_truth')
                        ->hiddenLabel()
                        ->view('filament.infolists.entries.governance-artifact-truth')
                        ->state(fn (EvidenceSnapshot $record): array => static::truthState($record))
                        ->columnSpanFull(),
                ])
                ->columnSpanFull(),
            Section::make('Snapshot')
                ->schema([
                    TextEntry::make('status')
                        ->badge()
                        ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EvidenceSnapshotStatus))
                        ->color(BadgeRenderer::color(BadgeDomain::EvidenceSnapshotStatus))
                        ->icon(BadgeRenderer::icon(BadgeDomain::EvidenceSnapshotStatus))
                        ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EvidenceSnapshotStatus)),
                    TextEntry::make('completeness_state')
                        ->label('Completeness')
                        ->badge()
                        ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EvidenceCompleteness))
                        ->color(BadgeRenderer::color(BadgeDomain::EvidenceCompleteness))
                        ->icon(BadgeRenderer::icon(BadgeDomain::EvidenceCompleteness))
                        ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EvidenceCompleteness)),
                    TextEntry::make('tenant.name')->label('ManagedEnvironment'),
                    TextEntry::make('generated_at')->dateTime()->placeholder('—'),
                    TextEntry::make('expires_at')->dateTime()->placeholder('—'),
                    TextEntry::make('operationRun.id')
                        ->label('Operation')
                        ->formatStateUsing(fn (?int $state): string => $state ? '#'.$state : '—')
                        ->url(fn (EvidenceSnapshot $record): ?string => $record->operation_run_id ? OperationRunLinks::tenantlessView((int) $record->operation_run_id) : null)
                        ->openUrlInNewTab()
                        ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                    TextEntry::make('fingerprint')->copyable()->placeholder('—')->columnSpanFull()->fontFamily('mono')
                        ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                    TextEntry::make('previous_fingerprint')->copyable()->placeholder('—')->columnSpanFull()->fontFamily('mono')
                        ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                ])
                ->columns(2),
            Section::make('Summary')
                ->schema([
                    TextEntry::make('summary.finding_count')->label('Findings')->placeholder('—'),
                    TextEntry::make('summary.report_count')->label('Reports')->placeholder('—'),
                    TextEntry::make('summary.operation_count')->label('Operations')->placeholder('—'),
                    TextEntry::make('summary.missing_dimensions')->label(static::evidenceCompletenessCountLabel(EvidenceCompletenessState::Missing->value))->placeholder('—'),
                    TextEntry::make('summary.stale_dimensions')->label(static::evidenceCompletenessCountLabel(EvidenceCompletenessState::Stale->value))->placeholder('—'),
                ])
                ->columns(2),
            Section::make('Related context')
                ->schema([
                    ViewEntry::make('related_context')
                        ->label('')
                        ->view('filament.infolists.entries.related-context')
                        ->state(fn (EvidenceSnapshot $record): array => static::relatedContextEntries($record))
                        ->columnSpanFull(),
                ])
                ->columnSpanFull(),
            Section::make('Evidence dimensions')
                ->schema([
                    RepeatableEntry::make('items')
                        ->hiddenLabel()
                        ->schema([
                            TextEntry::make('artifact_source_family')
                                ->label('Source family')
                                ->badge()
                                ->state(fn (EvidenceSnapshotItem $record): string => static::artifactDescriptorValue($record, 'source_family'))
                                ->formatStateUsing(fn (string $state): string => Str::headline($state)),
                            TextEntry::make('artifact_source_kind')
                                ->label('Source kind')
                                ->state(fn (EvidenceSnapshotItem $record): string => static::artifactDescriptorValue($record, 'source_kind'))
                                ->formatStateUsing(fn (string $state): string => Str::headline($state)),
                            TextEntry::make('artifact_source_target')
                                ->label('Source target')
                                ->state(fn (EvidenceSnapshotItem $record): string => static::artifactDescriptorValue($record, 'source_target_kind'))
                                ->formatStateUsing(fn (string $state): string => Str::headline($state)),
                            TextEntry::make('artifact_control_key')
                                ->label('Control')
                                ->state(fn (EvidenceSnapshotItem $record): ?string => static::artifactDescriptorNullableValue($record, 'control_key'))
                                ->formatStateUsing(fn (string $state): string => Str::headline($state))
                                ->placeholder('—'),
                            TextEntry::make('dimension_key')->label('Dimension')
                                ->formatStateUsing(fn (string $state): string => Str::headline($state)),
                            TextEntry::make('state')
                                ->badge()
                                ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EvidenceCompleteness))
                                ->color(BadgeRenderer::color(BadgeDomain::EvidenceCompleteness))
                                ->icon(BadgeRenderer::icon(BadgeDomain::EvidenceCompleteness))
                                ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EvidenceCompleteness)),
                            TextEntry::make('source_kind')->label('Provider source detail')
                                ->formatStateUsing(fn (string $state): string => Str::headline($state)),
                            TextEntry::make('freshness_at')->dateTime()->placeholder('—'),
                            ViewEntry::make('summary_payload_highlights')
                                ->label('Summary')
                                ->view('filament.infolists.entries.evidence-dimension-summary')
                                ->state(fn (EvidenceSnapshotItem $record): array => static::dimensionSummaryPresentation($record))
                                ->columnSpanFull(),
                            ViewEntry::make('summary_payload_raw')
                                ->label('Raw summary JSON')
                                ->view('filament.infolists.entries.snapshot-json')
                                ->state(fn (EvidenceSnapshotItem $record): array => is_array($record->summary_payload) ? $record->summary_payload : [])
                                ->hidden(fn (): bool => static::isCustomerWorkspaceFlow())
                                ->columnSpanFull(),
                        ])
                        ->columns(4),
                ]),
        ]);
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    public static function relatedContextEntries(EvidenceSnapshot $record): array
    {
        $entries = [];

        if (! static::isCustomerWorkspaceFlow() && is_numeric($record->operation_run_id)) {
            $entries[] = RelatedContextEntry::available(
                key: 'operation_run',
                label: 'Operation',
                value: sprintf('#%d', (int) $record->operation_run_id),
                secondaryValue: 'Open the latest evidence refresh operation.',
                targetUrl: OperationRunLinks::tenantlessView((int) $record->operation_run_id),
                targetKind: 'canonical_page',
                priority: 10,
                actionLabel: OperationRunLinks::openLabel(),
                contextBadge: 'Operations',
            )->toArray();
        }

        $pack = $record->reviewPacks()
            ->latest('created_at')
            ->first();

        if ($pack instanceof \App\Models\ReviewPack && $pack->tenant instanceof ManagedEnvironment) {
            $packUrl = ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $pack->tenant);

            if (static::isCustomerWorkspaceFlow()) {
                $packUrl = static::appendQuery($packUrl, static::customerWorkspaceContextQuery());
            }

            $entries[] = RelatedContextEntry::available(
                key: 'review_pack',
                label: 'Review pack',
                value: sprintf('#%d', (int) $pack->getKey()),
                secondaryValue: 'Inspect the latest executive-pack output for this evidence basis.',
                targetUrl: $packUrl,
                targetKind: 'direct_record',
                priority: 20,
                actionLabel: 'View review pack',
                contextBadge: 'Reporting',
            )->toArray();
        }

        if ($record->tenant instanceof ManagedEnvironment) {
            $entries[] = RelatedContextEntry::available(
                key: 'customer_review_workspace',
                label: 'Customer workspace',
                value: $record->tenant->name,
                secondaryValue: 'Open the customer-safe review workspace prefiltered to this tenant.',
                targetUrl: CustomerReviewWorkspace::environmentFilterUrl($record->tenant),
                targetKind: 'canonical_page',
                priority: 30,
                actionLabel: 'Open customer workspace',
                contextBadge: 'Reporting',
            )->toArray();
        }

        return $entries;
    }

    public static function isCustomerWorkspaceFlow(): bool
    {
        return request()->query('source_surface') === CustomerReviewWorkspace::SOURCE_SURFACE;
    }

    /**
     * @return array<string, mixed>
     */
    private static function customerWorkspaceContextQuery(): array
    {
        return array_filter([
            'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
            'review_id' => request()->query('review_id'),
            'interpretation_version' => request()->query('interpretation_version'),
            'tenant_filter_id' => request()->query('tenant_filter_id'),
        ], static fn (mixed $value): bool => $value !== null && $value !== '');
    }

    /**
     * @param  array<string, mixed>  $query
     */
    private static function appendQuery(string $url, array $query): string
    {
        if ($query === []) {
            return $url;
        }

        return $url.(str_contains($url, '?') ? '&' : '?').http_build_query($query);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('created_at', 'desc')
            ->recordUrl(fn (EvidenceSnapshot $record): string => static::getUrl('view', ['record' => $record]))
            ->columns([
                Tables\Columns\TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EvidenceSnapshotStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::EvidenceSnapshotStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::EvidenceSnapshotStatus))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EvidenceSnapshotStatus))
                    ->sortable(),
                Tables\Columns\TextColumn::make('outcome')
                    ->label('Outcome')
                    ->badge()
                    ->getStateUsing(fn (EvidenceSnapshot $record): string => static::compressedOutcome($record)->primaryLabel)
                    ->color(fn (EvidenceSnapshot $record): string => static::compressedOutcome($record)->primaryBadge->color)
                    ->icon(fn (EvidenceSnapshot $record): ?string => static::compressedOutcome($record)->primaryBadge->icon)
                    ->iconColor(fn (EvidenceSnapshot $record): ?string => static::compressedOutcome($record)->primaryBadge->iconColor)
                    ->description(fn (EvidenceSnapshot $record): ?string => static::compressedOutcome($record)->primaryReason)
                    ->wrap(),
                Tables\Columns\TextColumn::make('generated_at')->dateTime()->sortable()->placeholder('—'),
                Tables\Columns\TextColumn::make('summary.finding_count')->label('Findings'),
                Tables\Columns\TextColumn::make('next_step')
                    ->label('Next step')
                    ->getStateUsing(fn (EvidenceSnapshot $record): string => static::compressedOutcome($record)->nextActionText)
                    ->wrap(),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('status')
                    ->options(BadgeCatalog::options(BadgeDomain::EvidenceSnapshotStatus, EvidenceSnapshotStatus::values())),
                Tables\Filters\SelectFilter::make('completeness_state')
                    ->options(BadgeCatalog::options(BadgeDomain::EvidenceCompleteness, EvidenceCompletenessState::values())),
            ])
            ->actions([
                Actions\ActionGroup::make([
                    UiEnforcement::forTableAction(
                        Actions\Action::make('expire')
                            ->label(GovernanceActionCatalog::rule('expire_snapshot')->canonicalLabel)
                            ->color('danger')
                            ->hidden(fn (EvidenceSnapshot $record): bool => ! static::canExpireRecord($record))
                            ->requiresConfirmation()
                            ->modalHeading(GovernanceActionCatalog::rule('expire_snapshot')->modalHeading)
                            ->modalDescription(GovernanceActionCatalog::rule('expire_snapshot')->modalDescription)
                            ->form([
                                Textarea::make('expiration_reason')
                                    ->label('Expiry reason')
                                    ->rows(4)
                                    ->required()
                                    ->maxLength(2000),
                            ])
                            ->action(function (EvidenceSnapshot $record, array $data): void {
                                $user = auth()->user();

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

                                app(EvidenceSnapshotService::class)->expire(
                                    $record,
                                    $user,
                                    (string) ($data['expiration_reason'] ?? ''),
                                );
                                static::truthEnvelope($record->refresh(), fresh: true);

                                Notification::make()->success()->title(
                                    GovernanceActionCatalog::rule('expire_snapshot')->successTitle,
                                )->send();
                            }),
                        fn (EvidenceSnapshot $record): EvidenceSnapshot => $record,
                    )
                        ->preserveVisibility()
                        ->requireCapability(Capabilities::EVIDENCE_MANAGE)
                        ->tooltip(UiTooltips::INSUFFICIENT_PERMISSION)
                        ->apply(),
                ])->label('More'),
            ])
            ->bulkActions([])
            ->emptyStateHeading('No evidence snapshots yet')
            ->emptyStateDescription('Create the first snapshot to capture immutable evidence for this tenant.')
            ->emptyStateActions([
                UiEnforcement::forAction(
                    Actions\Action::make('create_first_snapshot')
                        ->label('Create first snapshot')
                        ->icon('heroicon-o-plus')
                        ->action(fn (): mixed => static::executeGeneration([])),
                )
                    ->requireCapability(Capabilities::EVIDENCE_MANAGE)
                    ->tooltip(UiTooltips::INSUFFICIENT_PERMISSION)
                    ->apply(),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListEvidenceSnapshots::route('/'),
            'view' => new PageRegistration(
                page: Pages\ViewEvidenceSnapshot::class,
                route: fn (Panel $panel): Route => RouteFacade::get('/{record}', Pages\ViewEvidenceSnapshot::class)
                    ->whereNumber('record')
                    ->middleware(Pages\ViewEvidenceSnapshot::getRouteMiddleware($panel))
                    ->withoutMiddleware(Pages\ViewEvidenceSnapshot::getWithoutRouteMiddleware($panel)),
            ),
        ];
    }

    /**
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function dimensionSummaryPresentation(EvidenceSnapshotItem $item): array
    {
        $payload = is_array($item->summary_payload) ? $item->summary_payload : [];

        $presentation = match ($item->dimension_key) {
            'findings_summary' => static::findingsSummaryPresentation($payload),
            'permission_posture' => static::permissionPosturePresentation($payload),
            'entra_admin_roles' => static::entraAdminRolesPresentation($payload),
            'baseline_drift_posture' => static::baselineDriftPosturePresentation($payload),
            'operations_summary' => static::operationsSummaryPresentation($payload),
            default => static::genericSummaryPresentation($payload),
        };

        $presentation['artifact_sources'] = [static::artifactSourceSummary($item)];

        return $presentation;
    }

    private static function artifactDescriptorValue(EvidenceSnapshotItem $item, string $key): string
    {
        return (string) (static::artifactDescriptorNullableValue($item, $key) ?? 'unknown');
    }

    private static function artifactDescriptorNullableValue(EvidenceSnapshotItem $item, string $key): ?string
    {
        $descriptor = $item->artifactSourceDescriptor()->toArray();
        $value = $descriptor[$key] ?? null;

        return is_string($value) && trim($value) !== '' ? trim($value) : null;
    }

    /**
     * @return array{source_family: string, source_kind: string, source_target_kind: string, control_key: ?string, detector_key: ?string}
     */
    private static function artifactSourceSummary(EvidenceSnapshotItem $item): array
    {
        $descriptor = $item->artifactSourceDescriptor();

        return [
            'source_family' => $descriptor->sourceFamily,
            'source_kind' => $descriptor->sourceKind,
            'source_target_kind' => $descriptor->sourceTargetKind,
            'control_key' => $descriptor->controlKey,
            'detector_key' => $descriptor->detectorKey,
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function findingsSummaryPresentation(array $payload): array
    {
        $count = (int) ($payload['count'] ?? 0);
        $openCount = (int) ($payload['open_count'] ?? 0);
        $severityCounts = is_array($payload['severity_counts'] ?? null) ? $payload['severity_counts'] : [];
        $entries = is_array($payload['entries'] ?? null) ? $payload['entries'] : [];

        return [
            'summary' => sprintf('%d findings, %d open.', $count, $openCount),
            'highlights' => [
                ['label' => 'Findings', 'value' => (string) $count],
                ['label' => 'Open findings', 'value' => (string) $openCount],
                ['label' => 'Critical', 'value' => (string) ((int) ($severityCounts['critical'] ?? 0))],
                ['label' => 'High', 'value' => (string) ((int) ($severityCounts['high'] ?? 0))],
                ['label' => 'Medium', 'value' => (string) ((int) ($severityCounts['medium'] ?? 0))],
                ['label' => 'Low', 'value' => (string) ((int) ($severityCounts['low'] ?? 0))],
            ],
            'items' => collect($entries)
                ->map(fn (mixed $entry): ?string => is_array($entry) ? static::findingEntryLabel($entry) : null)
                ->filter()
                ->take(5)
                ->values()
                ->all(),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function permissionPosturePresentation(array $payload): array
    {
        $requiredCount = (int) ($payload['required_count'] ?? 0);
        $grantedCount = (int) ($payload['granted_count'] ?? 0);
        $postureScore = $payload['posture_score'] ?? null;
        $reportPayload = is_array($payload['payload'] ?? null) ? $payload['payload'] : [];

        return [
            'summary' => sprintf('%d of %d required permissions granted.', $grantedCount, $requiredCount),
            'highlights' => [
                ['label' => 'Granted permissions', 'value' => (string) $grantedCount],
                ['label' => 'Required permissions', 'value' => (string) $requiredCount],
                ['label' => 'Posture score', 'value' => $postureScore === null ? '—' : (string) $postureScore],
            ],
            'items' => static::namedItemsFromArray(
                Arr::get($reportPayload, 'missing_permissions', Arr::get($reportPayload, 'missing', [])),
                'No missing permission details captured.'
            ),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function entraAdminRolesPresentation(array $payload): array
    {
        $roleCount = (int) ($payload['role_count'] ?? 0);

        return [
            'summary' => sprintf('%d privileged Entra roles captured.', $roleCount),
            'highlights' => [
                ['label' => 'Role count', 'value' => (string) $roleCount],
            ],
            'items' => static::namedItemsFromArray($payload['roles'] ?? [], 'No role details captured.'),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function baselineDriftPosturePresentation(array $payload): array
    {
        $driftCount = (int) ($payload['drift_count'] ?? 0);
        $openDriftCount = (int) ($payload['open_drift_count'] ?? 0);

        return [
            'summary' => sprintf('%d drift findings, %d still open.', $driftCount, $openDriftCount),
            'highlights' => [
                ['label' => 'Drift findings', 'value' => (string) $driftCount],
                ['label' => 'Open drift findings', 'value' => (string) $openDriftCount],
            ],
            'items' => [],
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function operationsSummaryPresentation(array $payload): array
    {
        $operationCount = (int) ($payload['operation_count'] ?? 0);
        $failedCount = (int) ($payload['failed_count'] ?? 0);
        $partialCount = (int) ($payload['partial_count'] ?? 0);
        $entries = is_array($payload['entries'] ?? null) ? $payload['entries'] : [];
        $actionSummary = $failedCount === 0 && $partialCount === 0
            ? 'No action needed.'
            : sprintf('%d execution failures, %d need follow-up.', $failedCount, $partialCount);

        return [
            'summary' => sprintf('%d operations in the last 30 days. %s', $operationCount, $actionSummary),
            'highlights' => [
                ['label' => 'Operations', 'value' => (string) $operationCount],
                ['label' => 'Execution failures', 'value' => (string) $failedCount],
                ['label' => 'Needs follow-up', 'value' => (string) $partialCount],
            ],
            'items' => collect($entries)
                ->map(fn (mixed $entry): ?string => is_array($entry) ? static::operationEntryLabel($entry) : null)
                ->filter()
                ->take(5)
                ->values()
                ->all(),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array{summary:?string,highlights:list<array{label:string,value:string}>,items:list<string>}
     */
    private static function genericSummaryPresentation(array $payload): array
    {
        $highlights = collect($payload)
            ->reject(fn (mixed $value, string|int $key): bool => in_array((string) $key, ['entries', 'payload', 'roles'], true) || is_array($value))
            ->take(6)
            ->map(fn (mixed $value, string|int $key): array => [
                'label' => Str::headline((string) $key),
                'value' => static::stringifySummaryValue($value),
            ])
            ->values()
            ->all();

        return [
            'summary' => empty($highlights) ? 'No summary details captured.' : null,
            'highlights' => $highlights,
            'items' => [],
        ];
    }

    /**
     * @return list<string>
     */
    private static function namedItemsFromArray(mixed $items, string $emptyFallback): array
    {
        if (! is_array($items) || $items === []) {
            return [$emptyFallback];
        }

        $labels = collect($items)
            ->map(function (mixed $item): ?string {
                if (is_string($item)) {
                    return trim($item) !== '' ? $item : null;
                }

                if (! is_array($item)) {
                    return null;
                }

                foreach (['display_name', 'displayName', 'name', 'title', 'id'] as $key) {
                    $value = $item[$key] ?? null;

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

                return null;
            })
            ->filter()
            ->take(5)
            ->values()
            ->all();

        return $labels === [] ? [$emptyFallback] : $labels;
    }

    /**
     * @param  array<string, mixed>  $entry
     */
    private static function findingEntryLabel(array $entry): ?string
    {
        $title = $entry['title'] ?? null;
        $severity = $entry['severity'] ?? null;
        $status = $entry['status'] ?? null;

        if (! is_string($title) || trim($title) === '') {
            return null;
        }

        $parts = [trim($title)];

        if (is_string($severity) && trim($severity) !== '') {
            $parts[] = Str::headline($severity);
        }

        if (is_string($status) && trim($status) !== '') {
            $parts[] = Str::headline($status);
        }

        return implode(' · ', $parts);
    }

    /**
     * @param  array<string, mixed>  $entry
     */
    private static function operationEntryLabel(array $entry): ?string
    {
        $type = $entry['type'] ?? null;

        if (! is_string($type) || trim($type) === '') {
            return null;
        }

        $parts = [static::operationTypeLabel($type)];

        $stateLabel = static::operationEntryStateLabel($entry);

        if ($stateLabel !== null) {
            $parts[] = $stateLabel;
        }

        return implode(' · ', $parts);
    }

    public static function canExpireRecord(EvidenceSnapshot $record): bool
    {
        return (string) $record->status !== EvidenceSnapshotStatus::Expired->value;
    }

    private static function operationTypeLabel(string $type): string
    {
        $label = OperationCatalog::label($type);

        return $label === 'Unknown operation' ? 'Operation' : $label;
    }

    /**
     * @param  array<string, mixed>  $entry
     */
    private static function operationEntryStateLabel(array $entry): ?string
    {
        $status = is_string($entry['status'] ?? null) ? trim((string) $entry['status']) : null;
        $outcome = is_string($entry['outcome'] ?? null) ? trim((string) $entry['outcome']) : null;

        return match ($status) {
            OperationRunStatus::Queued->value => static::badgeLabel(BadgeDomain::OperationRunStatus, $status),
            OperationRunStatus::Running->value => static::badgeLabel(BadgeDomain::OperationRunStatus, $status),
            OperationRunStatus::Completed->value => match ($outcome) {
                OperationRunOutcome::Pending->value => static::badgeLabel(BadgeDomain::OperationRunStatus, $status),
                OperationRunOutcome::Succeeded->value,
                OperationRunOutcome::PartiallySucceeded->value,
                OperationRunOutcome::Blocked->value,
                OperationRunOutcome::Failed->value,
                OperationRunOutcome::Cancelled->value => static::badgeLabel(BadgeDomain::OperationRunOutcome, $outcome),
                default => static::badgeLabel(BadgeDomain::OperationRunStatus, $status),
            },
            default => $outcome !== null ? static::badgeLabel(BadgeDomain::OperationRunOutcome, $outcome) : null,
        };
    }

    private static function evidenceCompletenessCountLabel(string $state): string
    {
        return BadgeCatalog::spec(BadgeDomain::EvidenceCompleteness, $state)->label;
    }

    private static function badgeLabel(BadgeDomain $domain, ?string $state): ?string
    {
        if ($state === null || trim($state) === '') {
            return null;
        }

        $label = BadgeCatalog::spec($domain, $state)->label;

        return $label === 'Unknown' ? null : $label;
    }

    private static function truthEnvelope(EvidenceSnapshot $record, bool $fresh = false): ArtifactTruthEnvelope
    {
        $presenter = app(ArtifactTruthPresenter::class);

        return $fresh
            ? $presenter->forEvidenceSnapshotFresh($record)
            : $presenter->forEvidenceSnapshot($record);
    }

    /**
     * @return array<string, mixed>
     */
    private static function truthState(EvidenceSnapshot $record, bool $fresh = false): array
    {
        $presenter = app(ArtifactTruthPresenter::class);
        $truth = $fresh
            ? static::truthEnvelope($record, true)
            : static::truthEnvelope($record);

        return $presenter->surfaceStateFor($record, SurfaceCompressionContext::evidenceSnapshot(), $fresh)
            ?? $truth->toArray(static::compressedOutcome($record, $fresh));
    }

    private static function compressedOutcome(EvidenceSnapshot $record, bool $fresh = false): CompressedGovernanceOutcome
    {
        $presenter = app(ArtifactTruthPresenter::class);

        return $presenter->compressedOutcomeFor($record, SurfaceCompressionContext::evidenceSnapshot(), $fresh)
            ?? $presenter->compressedOutcomeFromEnvelope(
                static::truthEnvelope($record, $fresh),
                SurfaceCompressionContext::evidenceSnapshot(),
            );
    }

    private static function stringifySummaryValue(mixed $value): string
    {
        return match (true) {
            $value === null => '—',
            is_bool($value) => $value ? 'Yes' : 'No',
            is_scalar($value) => (string) $value,
            default => '—',
        };
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public static function executeGeneration(array $data): void
    {
        $tenant = static::resolveTenantContextForCurrentPanel();
        $user = auth()->user();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User) {
            Notification::make()->danger()->title('Unable to create snapshot — missing context.')->send();

            return;
        }

        $snapshot = app(EvidenceSnapshotService::class)->generate(
            tenant: $tenant,
            user: $user,
            allowStale: (bool) ($data['allow_stale'] ?? false),
        );
        static::truthEnvelope($snapshot->refresh(), fresh: true);

        if (! $snapshot->wasRecentlyCreated) {
            Notification::make()
                ->success()
                ->title('Snapshot already available')
                ->body('A matching active snapshot already exists. No new run was started.')
                ->actions([
                    Actions\Action::make('view_snapshot')
                        ->label('View snapshot')
                        ->url(static::getUrl('view', ['record' => $snapshot], tenant: $tenant)),
                ])
                ->send();

            return;
        }

        Notification::make()
            ->success()
            ->title('Create snapshot queued')
            ->body('The snapshot is being generated in the background.')
            ->actions([
                Actions\Action::make('view_run')
                    ->label(OperationRunLinks::openLabel())
                    ->url($snapshot->operation_run_id ? OperationRunLinks::tenantlessView((int) $snapshot->operation_run_id) : static::getUrl('view', ['record' => $snapshot], tenant: $tenant)),
            ])
            ->send();
    }
}
