<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Concerns\CleansAdminTenantResourceQueryParameter;
use App\Filament\Pages\BaselineCompareMatrix;
use App\Filament\Resources\BaselineProfileResource\Pages;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Auth\CapabilityResolver;
use App\Services\Baselines\BaselineSnapshotTruthResolver;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Baselines\BaselineCaptureMode;
use App\Support\Baselines\BaselineFullContentRolloutGate;
use App\Support\Baselines\BaselineProfileStatus;
use App\Support\Baselines\BaselineReasonCodes;
use App\Support\Baselines\BaselineScope;
use App\Support\Baselines\Compare\CompareStrategyRegistry;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Inventory\InventoryPolicyTypeMeta;
use App\Support\Navigation\CrossResourceNavigationMatrix;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\RelatedContextEntry;
use App\Support\Navigation\RelatedNavigationResolver;
use App\Support\OperationCatalog;
use App\Support\OperationRunType;
use App\Support\Rbac\WorkspaceUiEnforcement;
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\ReasonTranslation\ReasonResolutionEnvelope;
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\Actions\ActionGroup;
use Filament\Facades\Filament;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Unique;
use InvalidArgumentException;
use UnitEnum;

class BaselineProfileResource extends Resource
{
    use CleansAdminTenantResourceQueryParameter;

    protected static bool $isDiscovered = false;

    protected static bool $isScopedToTenant = false;

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

    protected static ?string $slug = 'baseline-profiles';

    protected static bool $isGloballySearchable = false;

    protected static ?string $recordTitleAttribute = 'name';

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

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

    protected static ?string $navigationLabel = 'Baselines';

    protected static ?int $navigationSort = 1;

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

        return NavigationScope::shouldRegisterEnvironmentNavigation()
            && parent::shouldRegisterNavigation();
    }

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

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

        $workspace = self::resolveWorkspace();

        if (! $workspace instanceof Workspace) {
            return false;
        }

        $resolver = app(\App\Services\Auth\WorkspaceCapabilityResolver::class);

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

    public static function canCreate(): bool
    {
        return self::hasManageCapability();
    }

    public static function canEdit(Model $record): bool
    {
        return self::hasManageCapability();
    }

    public static function canDelete(Model $record): bool
    {
        return self::hasManageCapability();
    }

    public static function canView(Model $record): bool
    {
        return self::canViewAny();
    }

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::CrudListAndView, ActionSurfaceType::CrudListFirstResource)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Header action: Create baseline profile (capability-gated).')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Clickable-row inspection stays primary while Edit leads and archive trails inside "More".')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'No bulk mutations for baseline profiles in v1.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'List defines empty-state create CTA.')
            ->satisfy(ActionSurfaceSlot::DetailHeader, 'View page keeps one state-sensitive primary action, moves snapshot and compare-matrix navigation into contextual related context, and groups secondary actions under "More".');
    }

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

        return parent::getEloquentQuery()
            ->with(['activeSnapshot', 'createdByUser'])
            ->when(
                $workspaceId !== null,
                fn (Builder $query): Builder => $query->where('workspace_id', (int) $workspaceId),
            )
            ->when(
                $workspaceId === null,
                fn (Builder $query): Builder => $query->whereRaw('1 = 0'),
            );
    }

    public static function form(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('Profile')
                    ->schema([
                        TextInput::make('name')
                            ->required()
                            ->maxLength(255)
                            ->rule(fn (?BaselineProfile $record): Unique => Rule::unique('baseline_profiles', 'name')
                                ->where('workspace_id', $record?->workspace_id ?? app(WorkspaceContext::class)->currentWorkspaceId(request()))
                                ->ignore($record))
                            ->helperText('A descriptive name for this baseline profile.'),
                        Textarea::make('description')
                            ->rows(3)
                            ->maxLength(1000)
                            ->helperText('Explain the purpose and scope of this baseline.'),
                    ]),
                Section::make('Controls')
                    ->schema([
                        Select::make('status')
                            ->required()
                            ->options(fn (?BaselineProfile $record): array => self::statusOptionsForRecord($record))
                            ->default(BaselineProfileStatus::Draft->value)
                            ->native(false)
                            ->disabled(fn (?BaselineProfile $record): bool => $record?->status === BaselineProfileStatus::Archived)
                            ->helperText(fn (?BaselineProfile $record): string => match ($record?->status) {
                                BaselineProfileStatus::Archived => 'Archived baselines cannot be reactivated.',
                                BaselineProfileStatus::Active => 'Changing status to Archived is permanent.',
                                default => 'Only active baselines are enforced during compliance checks.',
                            }),
                        Select::make('capture_mode')
                            ->label('Capture mode')
                            ->required()
                            ->options(BaselineCaptureMode::selectOptions())
                            ->default(BaselineCaptureMode::Opportunistic->value)
                            ->native(false)
                            ->disabled(fn (?BaselineProfile $record): bool => $record?->status === BaselineProfileStatus::Archived)
                            ->disableOptionWhen(function (string $value): bool {
                                if ($value !== BaselineCaptureMode::FullContent->value) {
                                    return false;
                                }

                                return ! app(BaselineFullContentRolloutGate::class)->enabled();
                            })
                            ->helperText(fn (): string => app(BaselineFullContentRolloutGate::class)->enabled()
                                ? 'Full content capture enables deep drift detection by capturing policy evidence on demand.'
                                : 'Full content capture is currently disabled by rollout configuration.'),
                        TextInput::make('version_label')
                            ->label('Version label')
                            ->maxLength(50)
                            ->placeholder('e.g. v2.1 — February rollout')
                            ->helperText('Optional label to identify this version.'),
                        Select::make('scope_jsonb.policy_types')
                            ->label('Policy types')
                            ->multiple()
                            ->options(self::policyTypeOptions())
                            ->live()
                            ->helperText('Leave empty to include all supported policy types (excluding foundations).')
                            ->native(false),
                        Select::make('scope_jsonb.foundation_types')
                            ->label('Foundations')
                            ->multiple()
                            ->options(self::foundationTypeOptions())
                            ->live()
                            ->helperText('Leave empty to exclude foundations. Select foundations to include them.')
                            ->native(false),
                        Placeholder::make('metadata')
                            ->label('Last modified')
                            ->content(fn (?BaselineProfile $record): string => $record?->updated_at
                                ? $record->updated_at->diffForHumans()
                                : '—')
                            ->visible(fn (?BaselineProfile $record): bool => $record !== null),
                    ])
                    ->columns(2),
                Section::make('Governed subject summary')
                    ->schema([
                        Placeholder::make('scope_summary_display')
                            ->label('Scope summary')
                            ->content(function (Get $get): string {
                                return self::scopeSummaryText(self::formScopePayload($get));
                            })
                            ->columnSpanFull(),
                        Placeholder::make('scope_support_readiness_display')
                            ->label('Support readiness')
                            ->content(function (Get $get): string {
                                return self::scopeSupportReadinessText(self::formScopePayload($get));
                            }),
                        Placeholder::make('scope_selection_feedback_display')
                            ->label('Selection feedback')
                            ->content(function (Get $get): string {
                                return self::scopeSelectionFeedbackText(self::formScopePayload($get)) ?? 'Selections are valid for the current Intune-first workflow.';
                            }),
                    ])
                    ->columns(2),
            ]);
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('Profile')
                    ->schema([
                        TextEntry::make('name'),
                        TextEntry::make('status')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::BaselineProfileStatus))
                            ->color(BadgeRenderer::color(BadgeDomain::BaselineProfileStatus))
                            ->icon(BadgeRenderer::icon(BadgeDomain::BaselineProfileStatus)),
                        TextEntry::make('capture_mode')
                            ->label('Capture mode')
                            ->badge()
                            ->formatStateUsing(function (mixed $state): string {
                                if ($state instanceof BaselineCaptureMode) {
                                    return $state->label();
                                }

                                $parsed = is_string($state) ? BaselineCaptureMode::tryFrom($state) : null;

                                return $parsed?->label() ?? (is_string($state) ? $state : '—');
                            })
                            ->color(function (mixed $state): string {
                                $mode = $state instanceof BaselineCaptureMode
                                    ? $state
                                    : (is_string($state) ? BaselineCaptureMode::tryFrom($state) : null);

                                return match ($mode) {
                                    BaselineCaptureMode::FullContent => 'success',
                                    BaselineCaptureMode::Opportunistic => 'warning',
                                    BaselineCaptureMode::MetaOnly => 'gray',
                                    default => 'gray',
                                };
                            }),
                        TextEntry::make('version_label')
                            ->label('Version')
                            ->placeholder('—'),
                        TextEntry::make('description')
                            ->placeholder('No description')
                            ->columnSpanFull(),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),
                Section::make('Scope')
                    ->schema([
                        TextEntry::make('governed_subject_summary')
                            ->label('Governed subject summary')
                            ->state(fn (BaselineProfile $record): string => self::scopeSummaryText(self::scopePayload($record)))
                            ->columnSpanFull(),
                        TextEntry::make('scope_support_readiness')
                            ->label('Support readiness')
                            ->state(fn (BaselineProfile $record): string => self::scopeSupportReadinessText(self::scopePayload($record))),
                        TextEntry::make('scope_normalization_lineage')
                            ->label('Normalization lineage')
                            ->state(fn (BaselineProfile $record): string => self::scopeNormalizationLineageText($record))
                            ->columnSpanFull(),
                        TextEntry::make('scope_jsonb.policy_types')
                            ->label('Policy types')
                            ->badge()
                            ->formatStateUsing(function (string $state): string {
                                $options = self::policyTypeOptions();

                                return $options[$state] ?? $state;
                            })
                            ->placeholder('All supported policy types (excluding foundations)'),
                        TextEntry::make('scope_jsonb.foundation_types')
                            ->label('Foundations')
                            ->badge()
                            ->formatStateUsing(function (string $state): string {
                                $options = self::foundationTypeOptions();

                                return $options[$state] ?? $state;
                            })
                            ->placeholder('None'),
                    ])
                    ->columnSpanFull(),
                Section::make('Baseline truth')
                    ->schema([
                        TextEntry::make('current_snapshot_truth')
                            ->label('Current snapshot')
                            ->state(fn (BaselineProfile $record): string => self::currentSnapshotLabel($record)),
                        TextEntry::make('latest_attempted_snapshot_truth')
                            ->label('Latest attempt')
                            ->state(fn (BaselineProfile $record): string => self::latestAttemptedSnapshotLabel($record)),
                        TextEntry::make('compare_readiness')
                            ->label('Compare readiness')
                            ->badge()
                            ->state(fn (BaselineProfile $record): string => self::compareReadinessLabel($record))
                            ->color(fn (BaselineProfile $record): string => self::compareReadinessColor($record))
                            ->icon(fn (BaselineProfile $record): ?string => self::compareReadinessIcon($record)),
                        TextEntry::make('baseline_next_step')
                            ->label('Next step')
                            ->state(fn (BaselineProfile $record): string => self::profileNextStep($record))
                            ->columnSpanFull(),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),
                Section::make('Related context')
                    ->schema([
                        ViewEntry::make('related_context')
                            ->label('')
                            ->view('filament.infolists.entries.related-context')
                            ->state(fn (BaselineProfile $record): array => self::detailRelatedContextEntries($record))
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
                Section::make('Metadata')
                    ->schema([
                        TextEntry::make('createdByUser.name')
                            ->label('Created by')
                            ->placeholder('—'),
                        TextEntry::make('created_at')
                            ->dateTime(),
                        TextEntry::make('updated_at')
                            ->dateTime(),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),
            ]);
    }

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

        $snapshotEntry = app(RelatedNavigationResolver::class)
            ->headerEntries(CrossResourceNavigationMatrix::SOURCE_BASELINE_PROFILE, $record)[0] ?? null;

        if ($snapshotEntry instanceof RelatedContextEntry) {
            $entries[] = $snapshotEntry->toArray();
        }

        $entries[] = RelatedContextEntry::available(
            key: 'compare_matrix',
            label: 'Compare matrix',
            value: 'Review compare matrix',
            secondaryValue: $record->resolveCurrentConsumableSnapshot() instanceof BaselineSnapshot
                ? 'Use the latest consumable snapshot to inspect compare outcomes.'
                : 'Open the matrix to inspect compare readiness and previous results.',
            targetUrl: self::compareMatrixUrl($record),
            targetKind: 'canonical_page',
            priority: 20,
            actionLabel: 'Open compare matrix',
            contextBadge: 'Comparison',
        )->toArray();

        return $entries;
    }

    public static function table(Table $table): Table
    {
        $workspace = self::resolveWorkspace();

        return $table
            ->defaultSort('name')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::resource())
            ->recordUrl(fn (BaselineProfile $record): string => static::getUrl('view', ['record' => $record]))
            ->columns([
                TextColumn::make('name')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::BaselineProfileStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::BaselineProfileStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::BaselineProfileStatus))
                    ->sortable(),
                TextColumn::make('capture_mode')
                    ->label('Capture mode')
                    ->badge()
                    ->formatStateUsing(function (mixed $state): string {
                        if ($state instanceof BaselineCaptureMode) {
                            return $state->label();
                        }

                        $parsed = is_string($state) ? BaselineCaptureMode::tryFrom($state) : null;

                        return $parsed?->label() ?? (is_string($state) ? $state : '—');
                    })
                    ->color(function (mixed $state): string {
                        $mode = $state instanceof BaselineCaptureMode
                            ? $state
                            : (is_string($state) ? BaselineCaptureMode::tryFrom($state) : null);

                        return match ($mode) {
                            BaselineCaptureMode::FullContent => 'success',
                            BaselineCaptureMode::Opportunistic => 'warning',
                            BaselineCaptureMode::MetaOnly => 'gray',
                            default => 'gray',
                        };
                    })
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('version_label')
                    ->label('Version')
                    ->placeholder('—'),
                TextColumn::make('tenant_assignments_count')
                    ->label('Assigned environments')
                    ->counts('tenantAssignments'),
                TextColumn::make('current_snapshot_truth')
                    ->label('Current snapshot')
                    ->getStateUsing(fn (BaselineProfile $record): string => self::currentSnapshotLabel($record))
                    ->description(fn (BaselineProfile $record): ?string => self::currentSnapshotDescription($record))
                    ->wrap(),
                TextColumn::make('latest_attempted_snapshot_truth')
                    ->label('Latest attempt')
                    ->getStateUsing(fn (BaselineProfile $record): string => self::latestAttemptedSnapshotLabel($record))
                    ->description(fn (BaselineProfile $record): ?string => self::latestAttemptedSnapshotDescription($record))
                    ->wrap(),
                TextColumn::make('compare_readiness')
                    ->label('Compare readiness')
                    ->badge()
                    ->getStateUsing(fn (BaselineProfile $record): string => self::compareReadinessLabel($record))
                    ->color(fn (BaselineProfile $record): string => self::compareReadinessColor($record))
                    ->icon(fn (BaselineProfile $record): ?string => self::compareReadinessIcon($record))
                    ->wrap(),
                TextColumn::make('baseline_next_step')
                    ->label('Next step')
                    ->getStateUsing(fn (BaselineProfile $record): string => self::profileNextStep($record))
                    ->wrap(),
                TextColumn::make('created_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                \Filament\Tables\Filters\SelectFilter::make('status')
                    ->options(FilterOptionCatalog::baselineProfileStatuses()),
            ])
            ->actions([
                ActionGroup::make([
                    Action::make('edit')
                        ->label('Edit')
                        ->url(fn (BaselineProfile $record): string => static::getUrl('edit', ['record' => $record]))
                        ->icon('heroicon-o-pencil-square')
                        ->visible(fn (): bool => self::hasManageCapability()),
                    self::archiveTableAction($workspace),
                ])->label('More'),
            ])
            ->bulkActions([])
            ->emptyStateHeading('No baseline profiles')
            ->emptyStateDescription('Create a baseline profile to define what "good" looks like for your tenants.')
            ->emptyStateActions([
                Action::make('create')
                    ->label('Create baseline profile')
                    ->url(fn (): string => static::getUrl('create'))
                    ->icon('heroicon-o-plus')
                    ->visible(fn (): bool => self::hasManageCapability()),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            BaselineProfileResource\RelationManagers\BaselineTenantAssignmentsRelationManager::class,
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListBaselineProfiles::route('/'),
            'create' => Pages\CreateBaselineProfile::route('/create'),
            'view' => Pages\ViewBaselineProfile::route('/{record}'),
            'compare-matrix' => BaselineCompareMatrix::route('/{record}/compare-matrix'),
            'edit' => Pages\EditBaselineProfile::route('/{record}/edit'),
        ];
    }

    public static function compareMatrixUrl(BaselineProfile|int $profile): string
    {
        return static::getUrl('compare-matrix', ['record' => $profile], panel: 'admin');
    }

    /**
     * @param  array<string, mixed>|null  $scopePayload
     */
    public static function scopeSummaryText(?array $scopePayload): string
    {
        try {
            $scope = BaselineScope::fromJsonb($scopePayload);
        } catch (InvalidArgumentException) {
            return 'Invalid governed subject selection.';
        }

        $groups = collect($scope->summaryGroups());

        if ($groups->isEmpty()) {
            return 'No governed subjects selected.';
        }

        return $groups
            ->map(function (array $group) use ($scopePayload): string {
                $selectedSubjectTypes = $group['selected_subject_types'];

                if ($group['domain_key'] === 'intune'
                    && $group['subject_class'] === 'policy'
                    && is_array($scopePayload)
                    && (($scopePayload['policy_types'] ?? []) === [])) {
                    return $group['group_label'].': all supported Intune policy types';
                }

                if ($selectedSubjectTypes === []) {
                    return $group['group_label'].': none';
                }

                return $group['group_label'].': '.implode(', ', $selectedSubjectTypes);
            })
            ->implode('; ');
    }

    /**
     * @param  array<string, mixed>|null  $scopePayload
     */
    public static function scopeSupportReadinessText(?array $scopePayload): string
    {
        try {
            $scope = BaselineScope::fromJsonb($scopePayload);
        } catch (InvalidArgumentException) {
            return 'Capture: blocked. Compare: blocked.';
        }

        $capture = $scope->operationEligibility('capture');
        $compare = $scope->operationEligibility('compare');

        return sprintf(
            'Capture: %s. Compare: %s.',
            $capture['ok'] ? 'ready' : 'blocked',
            $compare['ok'] ? 'ready' : 'blocked',
        );
    }

    /**
     * @param  array<string, mixed>|null  $scopePayload
     */
    public static function scopeSelectionFeedbackText(?array $scopePayload): ?string
    {
        try {
            $scope = BaselineScope::fromJsonb($scopePayload);
        } catch (InvalidArgumentException $exception) {
            return $exception->getMessage();
        }

        if ($scope->normalizationLineage()['save_forward_required']) {
            return 'This Intune-first selection will be saved forward as canonical governed-subject scope V2.';
        }

        return null;
    }

    /**
     * @return array<string, string>
     */
    public static function policyTypeOptions(): array
    {
        return collect(InventoryPolicyTypeMeta::supported())
            ->filter(fn (array $row): bool => filled($row['type'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['type'] => (string) ($row['label'] ?? $row['type']),
            ])
            ->sort()
            ->all();
    }

    /**
     * @return array<string, string>
     */
    public static function foundationTypeOptions(): array
    {
        return collect(InventoryPolicyTypeMeta::baselineSupportedFoundations())
            ->filter(fn (array $row): bool => filled($row['type'] ?? null))
            ->mapWithKeys(fn (array $row): array => [
                (string) $row['type'] => InventoryPolicyTypeMeta::baselineCompareLabel((string) $row['type']) ?? (string) ($row['label'] ?? $row['type']),
            ])
            ->sort()
            ->all();
    }

    /**
     * @param  array<string, mixed>  $metadata
     */
    public static function audit(BaselineProfile $record, AuditActionId $actionId, array $metadata): void
    {
        $workspace = $record->workspace;

        if ($workspace === null) {
            return;
        }

        $actor = auth()->user();

        app(WorkspaceAuditLogger::class)->log(
            workspace: $workspace,
            action: $actionId->value,
            context: ['metadata' => $metadata],
            actor: $actor instanceof User ? $actor : null,
            resourceType: 'baseline_profile',
            resourceId: (string) $record->getKey(),
        );
    }

    /**
     * Status options scoped to valid transitions from the current record state.
     *
     * @return array<string, string>
     */
    private static function statusOptionsForRecord(?BaselineProfile $record): array
    {
        if ($record === null) {
            return [BaselineProfileStatus::Draft->value => BaselineProfileStatus::Draft->label()];
        }

        $currentStatus = $record->status instanceof BaselineProfileStatus
            ? $record->status
            : (BaselineProfileStatus::tryFrom((string) $record->status) ?? BaselineProfileStatus::Draft);

        return $currentStatus->selectOptions();
    }

    private static function resolveWorkspace(): ?Workspace
    {
        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if ($workspaceId === null) {
            return null;
        }

        return Workspace::query()->whereKey($workspaceId)->first();
    }

    private static function hasManageCapability(): bool
    {
        $user = auth()->user();
        $workspace = self::resolveWorkspace();

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

        $resolver = app(\App\Services\Auth\WorkspaceCapabilityResolver::class);

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

    private static function archiveTableAction(?Workspace $workspace): Action
    {
        $action = Action::make('archive')
            ->label('Archive')
            ->icon('heroicon-o-archive-box')
            ->color('warning')
            ->requiresConfirmation()
            ->modalHeading('Archive baseline profile')
            ->modalDescription('Archiving is permanent in v1. This profile can no longer be used for captures or compares.')
            ->hidden(fn (BaselineProfile $record): bool => $record->status === BaselineProfileStatus::Archived)
            ->action(function (BaselineProfile $record): void {
                if (! self::hasManageCapability()) {
                    throw new AuthorizationException;
                }

                $record->forceFill(['status' => BaselineProfileStatus::Archived->value])->save();

                self::audit($record, AuditActionId::BaselineProfileArchived, [
                    'baseline_profile_id' => (int) $record->getKey(),
                    'name' => (string) $record->name,
                ]);

                Notification::make()
                    ->title('Baseline profile archived')
                    ->success()
                    ->send();
            });

        if ($workspace instanceof Workspace) {
            $action = WorkspaceUiEnforcement::forTableAction($action, $workspace)
                ->requireCapability(Capabilities::WORKSPACE_BASELINES_MANAGE)
                ->destructive()
                ->apply();
        }

        return $action;
    }

    private static function currentSnapshotLabel(BaselineProfile $profile): string
    {
        $snapshot = self::effectiveSnapshot($profile);

        if (! $snapshot instanceof BaselineSnapshot) {
            return 'No complete snapshot';
        }

        return self::snapshotReference($snapshot);
    }

    private static function currentSnapshotDescription(BaselineProfile $profile): ?string
    {
        $snapshot = self::effectiveSnapshot($profile);

        if (! $snapshot instanceof BaselineSnapshot) {
            return self::compareAvailabilityEnvelope($profile)?->shortExplanation;
        }

        return $snapshot->captured_at?->toDayDateTimeString();
    }

    private static function latestAttemptedSnapshotLabel(BaselineProfile $profile): string
    {
        $latestAttempt = self::latestAttemptedSnapshot($profile);

        if (! $latestAttempt instanceof BaselineSnapshot) {
            return 'No capture attempts yet';
        }

        $effectiveSnapshot = self::effectiveSnapshot($profile);

        if ($effectiveSnapshot instanceof BaselineSnapshot && (int) $effectiveSnapshot->getKey() === (int) $latestAttempt->getKey()) {
            return 'Matches current snapshot';
        }

        return self::snapshotReference($latestAttempt);
    }

    private static function latestAttemptedSnapshotDescription(BaselineProfile $profile): ?string
    {
        $latestAttempt = self::latestAttemptedSnapshot($profile);

        if (! $latestAttempt instanceof BaselineSnapshot) {
            return null;
        }

        $effectiveSnapshot = self::effectiveSnapshot($profile);

        if ($effectiveSnapshot instanceof BaselineSnapshot && (int) $effectiveSnapshot->getKey() === (int) $latestAttempt->getKey()) {
            return 'No newer attempt is pending.';
        }

        return $latestAttempt->captured_at?->toDayDateTimeString();
    }

    private static function compareReadinessLabel(BaselineProfile $profile): string
    {
        return match (self::compareAvailabilityReason($profile)) {
            BaselineReasonCodes::COMPARE_INVALID_SCOPE => 'Invalid scope',
            BaselineReasonCodes::COMPARE_MIXED_SCOPE => 'Mixed strategy scope',
            BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE => 'Unsupported governed subjects',
            default => self::compareAvailabilityEnvelope($profile)?->operatorLabel ?? 'Ready',
        };
    }

    private static function compareReadinessColor(BaselineProfile $profile): string
    {
        return match (self::compareAvailabilityReason($profile)) {
            null => 'success',
            BaselineReasonCodes::COMPARE_PROFILE_NOT_ACTIVE => 'gray',
            BaselineReasonCodes::COMPARE_INVALID_SCOPE,
            BaselineReasonCodes::COMPARE_MIXED_SCOPE,
            BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE => 'danger',
            default => 'warning',
        };
    }

    private static function compareReadinessIcon(BaselineProfile $profile): ?string
    {
        return match (self::compareAvailabilityReason($profile)) {
            null => 'heroicon-m-check-badge',
            BaselineReasonCodes::COMPARE_PROFILE_NOT_ACTIVE => 'heroicon-m-pause-circle',
            BaselineReasonCodes::COMPARE_INVALID_SCOPE,
            BaselineReasonCodes::COMPARE_MIXED_SCOPE,
            BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE => 'heroicon-m-no-symbol',
            default => 'heroicon-m-exclamation-triangle',
        };
    }

    private static function profileNextStep(BaselineProfile $profile): string
    {
        $compareAvailabilityReason = self::compareAvailabilityReason($profile);

        if ($compareAvailabilityReason === null) {
            $latestCaptureEnvelope = self::latestBaselineCaptureEnvelope($profile);

            if ($latestCaptureEnvelope instanceof ReasonResolutionEnvelope && trim($latestCaptureEnvelope->shortExplanation) !== '') {
                return $latestCaptureEnvelope->shortExplanation;
            }
        }

        return match ($compareAvailabilityReason) {
            BaselineReasonCodes::COMPARE_INVALID_SCOPE,
            BaselineReasonCodes::COMPARE_MIXED_SCOPE,
            BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE => 'Review the governed subject selection before starting compare.',
            default => self::compareAvailabilityEnvelope($profile)?->guidanceText() ?? 'No action needed.',
        };
    }

    private static function effectiveSnapshot(BaselineProfile $profile): ?BaselineSnapshot
    {
        return app(BaselineSnapshotTruthResolver::class)->resolveEffectiveSnapshot($profile);
    }

    private static function latestAttemptedSnapshot(BaselineProfile $profile): ?BaselineSnapshot
    {
        return app(BaselineSnapshotTruthResolver::class)->resolveLatestAttemptedSnapshot($profile);
    }

    private static function latestBaselineCaptureEnvelope(BaselineProfile $profile): ?ReasonResolutionEnvelope
    {
        $run = OperationRun::query()
            ->where('workspace_id', (int) $profile->workspace_id)
            ->whereIn('type', OperationCatalog::rawValuesForCanonical(OperationRunType::BaselineCapture->value))
            ->where('context->baseline_profile_id', (int) $profile->getKey())
            ->where('status', 'completed')
            ->orderByDesc('completed_at')
            ->orderByDesc('id')
            ->first();

        if (! $run instanceof OperationRun) {
            return null;
        }

        $reasonCode = data_get($run->context, 'reason_code');

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

        return app(ReasonPresenter::class)->forOperationRun($run, 'artifact_truth');
    }

    private static function compareAvailabilityReason(BaselineProfile $profile): ?string
    {
        $status = $profile->status instanceof BaselineProfileStatus
            ? $profile->status
            : BaselineProfileStatus::tryFrom((string) $profile->status);

        if ($status !== BaselineProfileStatus::Active) {
            return BaselineReasonCodes::COMPARE_PROFILE_NOT_ACTIVE;
        }

        try {
            $scope = BaselineScope::fromJsonb(self::scopePayload($profile));
        } catch (InvalidArgumentException) {
            return BaselineReasonCodes::COMPARE_INVALID_SCOPE;
        }

        if ($scope->allTypes() === []) {
            return BaselineReasonCodes::COMPARE_INVALID_SCOPE;
        }

        $selection = app(CompareStrategyRegistry::class)->select($scope);

        if ($selection->isMixed()) {
            return BaselineReasonCodes::COMPARE_MIXED_SCOPE;
        }

        if (! $selection->isSupported()) {
            return BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE;
        }

        $resolution = app(BaselineSnapshotTruthResolver::class)->resolveCompareSnapshot($profile);
        $reasonCode = $resolution['reason_code'] ?? null;

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

        if (! self::hasEligibleCompareTarget($profile)) {
            return BaselineReasonCodes::COMPARE_NO_ELIGIBLE_TARGET;
        }

        return null;
    }

    private static function compareAvailabilityEnvelope(BaselineProfile $profile): ?ReasonResolutionEnvelope
    {
        $reasonCode = self::compareAvailabilityReason($profile);

        if (! is_string($reasonCode)) {
            return null;
        }

        return app(ReasonPresenter::class)->forArtifactTruth($reasonCode, 'artifact_truth');
    }

    private static function snapshotReference(BaselineSnapshot $snapshot): string
    {
        $lifecycleLabel = BadgeCatalog::spec(BadgeDomain::BaselineSnapshotLifecycle, $snapshot->lifecycleState()->value)->label;

        return sprintf('Snapshot #%d (%s)', (int) $snapshot->getKey(), $lifecycleLabel);
    }

    private static function hasEligibleCompareTarget(BaselineProfile $profile): bool
    {
        $user = auth()->user();

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

        $tenantIds = BaselineTenantAssignment::query()
            ->where('workspace_id', (int) $profile->workspace_id)
            ->where('baseline_profile_id', (int) $profile->getKey())
            ->pluck('managed_environment_id')
            ->all();

        if ($tenantIds === []) {
            return false;
        }

        $resolver = app(CapabilityResolver::class);

        return ManagedEnvironment::query()
            ->where('workspace_id', (int) $profile->workspace_id)
            ->whereIn('id', $tenantIds)
            ->get(['id'])
            ->contains(fn (ManagedEnvironment $tenant): bool => $resolver->can($user, $tenant, Capabilities::TENANT_SYNC));
    }

    /**
     * @param  array<string, mixed>|null  $scopePayload
     */
    private static function formScopePayload(Get $get): ?array
    {
        $scopePayload = $get('scope_jsonb');

        return is_array($scopePayload) ? $scopePayload : null;
    }

    /**
     * @return array<string, mixed>|null
     */
    private static function scopePayload(BaselineProfile $profile): ?array
    {
        return $profile->rawScopeJsonb();
    }

    private static function scopeNormalizationLineageText(BaselineProfile $profile): string
    {
        try {
            $lineage = $profile->normalizedScope()->normalizationLineage();
        } catch (InvalidArgumentException) {
            return 'Stored scope is invalid and must be repaired before capture or compare can continue.';
        }

        if ($lineage['source_shape'] === 'legacy') {
            return 'Legacy Intune buckets are being normalized and will be saved forward as canonical V2 on the next successful save.';
        }

        return 'Canonical governed-subject scope V2 is already stored for this baseline profile.';
    }
}
