<?php

declare(strict_types=1);

namespace App\Filament\Pages;

use App\Filament\Resources\BaselineProfileResource;
use App\Filament\Resources\FindingResource;
use App\Models\BaselineProfile;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Services\Baselines\BaselineCompareService;
use App\Support\Auth\Capabilities;
use App\Support\Baselines\BaselineCompareMatrixBuilder;
use App\Support\Baselines\BaselineReasonCodes;
use App\Support\Baselines\Compare\CompareStrategyRegistry;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperationRunLinks;
use App\Support\OperationRunType;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\Rbac\WorkspaceUiEnforcement;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\Concerns\InteractsWithRecord;
use Filament\Resources\Pages\Page;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Schema;

class BaselineCompareMatrix extends Page implements HasForms
{
    use InteractsWithForms;
    use InteractsWithRecord;

    protected const MONITORING_PAGE_STATE_CONTRACT = [
        'surfaceKey' => 'baseline_compare_matrix',
        'surfaceType' => 'draft_apply_analysis',
        'stateFields' => [
            [
                'stateKey' => 'mode',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'policy_type',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'state',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'severity',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'tenant_sort',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'subject_sort',
                'stateClass' => 'active',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'discard_and_continue',
            ],
            [
                'stateKey' => 'subject_key',
                'stateClass' => 'inspect',
                'carrier' => 'query_param',
                'queryRole' => 'durable_restorable',
                'shareable' => true,
                'restorableOnRefresh' => true,
                'tenantSensitive' => false,
                'invalidFallback' => 'clear_selection_and_continue',
            ],
        ],
        'hydrationRule' => [
            'precedenceOrder' => ['query', 'default'],
            'appliesOnInitialMountOnly' => true,
            'activeStateBecomesAuthoritativeAfterMount' => true,
            'clearsOnTenantSwitch' => ['mode', 'policy_type', 'state', 'severity', 'tenant_sort', 'subject_sort', 'subject_key'],
            'invalidRequestedStateFallback' => 'discard_and_continue',
        ],
        'inspectContract' => [
            'primaryModel' => 'baseline_subject',
            'selectedStateKey' => 'focusedSubjectKey',
            'openedBy' => ['query_param', 'focus_link'],
            'presentation' => 'focused_matrix',
            'shareable' => true,
            'invalidSelectionFallback' => 'clear_selection_and_continue',
        ],
        'shareableStateKeys' => ['mode', 'policy_type', 'state', 'severity', 'tenant_sort', 'subject_sort', 'subject_key'],
        'localOnlyStateKeys' => [
            'draftSelectedPolicyTypes',
            'draftSelectedStates',
            'draftSelectedSeverities',
            'draftTenantSort',
            'draftSubjectSort',
        ],
    ];

    protected static bool $isDiscovered = false;

    protected static bool $shouldRegisterNavigation = false;

    protected static string $resource = BaselineProfileResource::class;

    protected static ?string $breadcrumb = 'Compare matrix';

    protected string $view = 'filament.pages.baseline-compare-matrix';

    public string $requestedMode = 'auto';

    /**
     * @var list<string>
     */
    public array $selectedPolicyTypes = [];

    /**
     * @var list<string>
     */
    public array $selectedStates = [];

    /**
     * @var list<string>
     */
    public array $selectedSeverities = [];

    public string $tenantSort = 'tenant_name';

    public string $subjectSort = 'deviation_breadth';

    public ?string $focusedSubjectKey = null;

    /**
     * @var list<string>
     */
    public array $draftSelectedPolicyTypes = [];

    /**
     * @var list<string>
     */
    public array $draftSelectedStates = [];

    /**
     * @var list<string>
     */
    public array $draftSelectedSeverities = [];

    public string $draftTenantSort = 'tenant_name';

    public string $draftSubjectSort = 'deviation_breadth';

    /**
     * @var array<string, mixed>
     */
    public array $matrix = [];

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forPage(ActionSurfaceProfile::ListOnlyReadOnly)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Header actions keep bounded navigation plus confirmation-gated compare fan-out for visible assigned environments.')
            ->exempt(ActionSurfaceSlot::InspectAffordance, 'The matrix intentionally forbids row click; only explicit tenant, subject, cell, and run drilldowns are rendered.')
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'The matrix does not use a row-level secondary-actions menu.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'The matrix has no bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'Blocked, empty, no-visible-tenant, and no-filter-match states render as explicit matrix empty states.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'The matrix is a page-level scan surface rather than a record detail header.');
    }

    /**
     * @return array<string, mixed>
     */
    public static function monitoringPageStateContract(): array
    {
        return self::MONITORING_PAGE_STATE_CONTRACT;
    }

    public function mount(int|string $record): void
    {
        $this->record = $this->resolveRecord($record);
        $this->hydrateFiltersFromRequest();
        $this->refreshMatrix();
        $this->form->fill($this->filterFormState());
    }

    public function form(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Grid::make([
                    'default' => 1,
                    'xl' => 2,
                ])
                    ->schema([
                        Grid::make([
                            'default' => 1,
                            'lg' => 5,
                        ])
                            ->schema([
                                Select::make('draftSelectedPolicyTypes')
                                    ->label('Governed subjects')
                                    ->options(fn (): array => $this->matrixOptions('policyTypeOptions'))
                                    ->multiple()
                                    ->searchable()
                                    ->preload()
                                    ->native(false)
                                    ->placeholder('All governed subjects')
                                    ->helperText(fn (): ?string => $this->matrixOptions('policyTypeOptions') === []
                                        ? 'Governed subject filters appear after a usable reference snapshot is available.'
                                        : null)
                                    ->extraFieldWrapperAttributes([
                                        'data-testid' => 'matrix-policy-type-filter',
                                    ])
                                    ->columnSpan([
                                        'lg' => 2,
                                    ]),
                                Select::make('draftSelectedStates')
                                    ->label('Technical states')
                                    ->options(fn (): array => $this->matrixOptions('stateOptions'))
                                    ->multiple()
                                    ->searchable()
                                    ->native(false)
                                    ->placeholder('All technical states')
                                    ->columnSpan([
                                        'lg' => 2,
                                    ]),
                                Select::make('draftSelectedSeverities')
                                    ->label('Severity')
                                    ->options(fn (): array => $this->matrixOptions('severityOptions'))
                                    ->multiple()
                                    ->searchable()
                                    ->native(false)
                                    ->placeholder('All severities'),
                            ])
                            ->columnSpan([
                                'xl' => 1,
                            ]),
                        Grid::make([
                            'default' => 1,
                            'md' => 2,
                            'xl' => 1,
                        ])
                            ->schema([
                                Select::make('draftTenantSort')
                                    ->label('ManagedEnvironment sort')
                                    ->options(fn (): array => $this->matrixOptions('tenantSortOptions'))
                                    ->default('tenant_name')
                                    ->native(false)
                                    ->extraFieldWrapperAttributes(['data-testid' => 'matrix-tenant-sort'])
                                    ->extraInputAttributes(['data-testid' => 'matrix-tenant-sort']),
                                Select::make('draftSubjectSort')
                                    ->label('Subject sort')
                                    ->options(fn (): array => $this->matrixOptions('subjectSortOptions'))
                                    ->default('deviation_breadth')
                                    ->native(false)
                                    ->extraFieldWrapperAttributes(['data-testid' => 'matrix-subject-sort'])
                                    ->extraInputAttributes(['data-testid' => 'matrix-subject-sort']),
                            ])
                            ->columnSpan([
                                'xl' => 1,
                            ]),
                    ]),
            ]);
    }

    protected function authorizeAccess(): void
    {
        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            abort(404);
        }

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

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

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

    public function getTitle(): string
    {
        /** @var BaselineProfile $profile */
        $profile = $this->getRecord();

        return 'Compare matrix: '.$profile->name;
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        $profile = $this->getRecord();

        $compareAssignedTenantsAction = Action::make('compareAssignedTenants')
            ->label('Compare assigned environments')
            ->icon('heroicon-o-play')
            ->requiresConfirmation()
            ->modalHeading('Compare assigned environments')
            ->modalDescription('Simulation only. This starts the normal environment-owned baseline compare path for the visible assigned set. No workspace umbrella run is created.')
            ->disabled(fn (): bool => $this->compareAssignedTenantsDisabledReason() !== null)
            ->tooltip(fn (): ?string => $this->compareAssignedTenantsDisabledReason())
            ->action(fn (): mixed => $this->compareAssignedTenants());

        $compareAssignedTenantsAction = WorkspaceUiEnforcement::forAction(
            $compareAssignedTenantsAction,
            fn (): ?Workspace => $this->workspace(),
        )
            ->requireCapability(Capabilities::WORKSPACE_BASELINES_MANAGE)
            ->preserveDisabled()
            ->tooltip('You need workspace baseline manage access to compare the visible assigned set.')
            ->apply()
            ->tooltip(function (): ?string {
                $user = auth()->user();
                $workspace = $this->workspace();

                if ($user instanceof User && $workspace instanceof Workspace) {
                    /** @var WorkspaceCapabilityResolver $resolver */
                    $resolver = app(WorkspaceCapabilityResolver::class);

                    if ($resolver->isMember($user, $workspace) && ! $resolver->can($user, $workspace, Capabilities::WORKSPACE_BASELINES_MANAGE)) {
                        return 'You need workspace baseline manage access to compare the visible assigned set.';
                    }
                }

                return $this->compareAssignedTenantsDisabledReason();
            });

        return [
            Action::make('backToBaselineProfile')
                ->label('Back to baseline profile')
                ->color('gray')
                ->url(BaselineProfileResource::getUrl('view', ['record' => $profile], panel: 'admin')),
            $compareAssignedTenantsAction,
        ];
    }

    public function applyFilters(): void
    {
        $this->selectedPolicyTypes = $this->normalizeQueryList($this->draftSelectedPolicyTypes);
        $this->selectedStates = $this->normalizeQueryList($this->draftSelectedStates);
        $this->selectedSeverities = $this->normalizeQueryList($this->draftSelectedSeverities);
        $this->tenantSort = $this->normalizeTenantSort($this->draftTenantSort);
        $this->subjectSort = $this->normalizeSubjectSort($this->draftSubjectSort);

        $this->redirect($this->filterUrl(), navigate: true);
    }

    public function resetFilters(): void
    {
        $this->selectedPolicyTypes = [];
        $this->selectedStates = [];
        $this->selectedSeverities = [];
        $this->tenantSort = 'tenant_name';
        $this->subjectSort = 'deviation_breadth';
        $this->focusedSubjectKey = null;
        $this->draftSelectedPolicyTypes = [];
        $this->draftSelectedStates = [];
        $this->draftSelectedSeverities = [];
        $this->draftTenantSort = 'tenant_name';
        $this->draftSubjectSort = 'deviation_breadth';

        $this->redirect($this->filterUrl(), navigate: true);
    }

    public function refreshMatrix(): void
    {
        $user = auth()->user();

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

        /** @var BaselineProfile $profile */
        $profile = $this->getRecord();

        $this->matrix = app(BaselineCompareMatrixBuilder::class)->build($profile, $user, [
            'policyTypes' => $this->selectedPolicyTypes,
            'states' => $this->selectedStates,
            'severities' => $this->selectedSeverities,
            'tenantSort' => $this->tenantSort,
            'subjectSort' => $this->subjectSort,
            'focusedSubjectKey' => $this->focusedSubjectKey,
        ]);
    }

    public function pollMatrix(): void
    {
        $this->refreshMatrix();
    }

    public function tenantCompareUrl(int $tenantId, ?string $subjectKey = null): ?string
    {
        $tenant = $this->tenant($tenantId);

        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return ManagedEnvironmentLinks::baselineCompareUrl($tenant, $this->navigationContext($tenant, $subjectKey)->toQuery());
    }

    public function findingUrl(int $tenantId, int $findingId, ?string $subjectKey = null): ?string
    {
        $tenant = $this->tenant($tenantId);

        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return FindingResource::getUrl(
            'view',
            [
                'record' => $findingId,
                ...$this->navigationContext($tenant, $subjectKey)->toQuery(),
            ],
            tenant: $tenant,
        );
    }

    public function runUrl(int $runId, ?int $tenantId = null, ?string $subjectKey = null): string
    {
        return OperationRunLinks::tenantlessView(
            $runId,
            $this->navigationContext(
                $tenantId !== null ? $this->tenant($tenantId) : null,
                $subjectKey,
            ),
        );
    }

    public function clearSubjectFocusUrl(): string
    {
        return static::getUrl($this->routeParameters([
            'subject_key' => null,
        ]), panel: 'admin');
    }

    public function modeUrl(string $mode): string
    {
        return $this->filterUrl([
            'mode' => $this->normalizeRequestedMode($mode),
        ]);
    }

    public function filterUrl(array $overrides = []): string
    {
        return static::getUrl($this->routeParameters($overrides), panel: 'admin');
    }

    public function activeFilterCount(): int
    {
        return count($this->selectedPolicyTypes)
            + count($this->selectedStates)
            + count($this->selectedSeverities)
            + ($this->focusedSubjectKey !== null ? 1 : 0);
    }

    public function hasStagedFilterChanges(): bool
    {
        return $this->draftFilterState() !== $this->appliedFilterState();
    }

    public function canUseCompactMode(): bool
    {
        return $this->visibleTenantCount() <= 1;
    }

    public function presentationModeLabel(string $mode): string
    {
        return match ($mode) {
            'dense' => 'Dense mode',
            'compact' => 'Compact mode',
            default => 'Auto mode',
        };
    }

    /**
     * @return array<string, int|string>
     */
    public function activeFilterSummary(): array
    {
        $summary = [];

        if ($this->selectedPolicyTypes !== []) {
            $summary['Governed subjects'] = count($this->selectedPolicyTypes);
        }

        if ($this->selectedStates !== []) {
            $summary['Technical states'] = count($this->selectedStates);
        }

        if ($this->selectedSeverities !== []) {
            $summary['Severity'] = count($this->selectedSeverities);
        }

        if ($this->focusedSubjectKey !== null) {
            $summary['Focused subject'] = $this->focusedSubjectKey;
        }

        return $summary;
    }

    /**
     * @return array<string, int|string>
     */
    public function stagedFilterSummary(): array
    {
        $summary = [];

        if ($this->draftSelectedPolicyTypes !== $this->selectedPolicyTypes) {
            $summary['Governed subjects'] = count($this->draftSelectedPolicyTypes);
        }

        if ($this->draftSelectedStates !== $this->selectedStates) {
            $summary['Technical states'] = count($this->draftSelectedStates);
        }

        if ($this->draftSelectedSeverities !== $this->selectedSeverities) {
            $summary['Severity'] = count($this->draftSelectedSeverities);
        }

        if ($this->draftTenantSort !== $this->tenantSort) {
            $summary['ManagedEnvironment sort'] = $this->draftTenantSort;
        }

        if ($this->draftSubjectSort !== $this->subjectSort) {
            $summary['Subject sort'] = $this->draftSubjectSort;
        }

        return $summary;
    }

    /**
     * @return array<string, mixed>
     */
    protected function getViewData(): array
    {
        return array_merge($this->matrix, [
            'profile' => $this->getRecord(),
            'currentFilters' => [
                'mode' => $this->requestedMode,
                'policy_type' => $this->selectedPolicyTypes,
                'state' => $this->selectedStates,
                'severity' => $this->selectedSeverities,
                'tenant_sort' => $this->tenantSort,
                'subject_sort' => $this->subjectSort,
                'subject_key' => $this->focusedSubjectKey,
            ],
            'draftFilters' => [
                'policy_type' => $this->draftSelectedPolicyTypes,
                'state' => $this->draftSelectedStates,
                'severity' => $this->draftSelectedSeverities,
                'tenant_sort' => $this->draftTenantSort,
                'subject_sort' => $this->draftSubjectSort,
            ],
            'presentationState' => $this->presentationState(),
        ]);
    }

    private function hydrateFiltersFromRequest(): void
    {
        $this->requestedMode = $this->normalizeRequestedMode(request()->query('mode', 'auto'));
        $this->selectedPolicyTypes = $this->normalizeQueryList(request()->query('policy_type', []));
        $this->selectedStates = $this->normalizeQueryList(request()->query('state', []));
        $this->selectedSeverities = $this->normalizeQueryList(request()->query('severity', []));
        $this->tenantSort = $this->normalizeTenantSort(request()->query('tenant_sort', 'tenant_name'));
        $this->subjectSort = $this->normalizeSubjectSort(request()->query('subject_sort', 'deviation_breadth'));
        $subjectKey = request()->query('subject_key');
        $this->focusedSubjectKey = is_string($subjectKey) && trim($subjectKey) !== '' ? trim($subjectKey) : null;
        $this->draftSelectedPolicyTypes = $this->selectedPolicyTypes;
        $this->draftSelectedStates = $this->selectedStates;
        $this->draftSelectedSeverities = $this->selectedSeverities;
        $this->draftTenantSort = $this->tenantSort;
        $this->draftSubjectSort = $this->subjectSort;
    }

    /**
     * @return array<string, mixed>
     */
    private function filterFormState(): array
    {
        return [
            'draftSelectedPolicyTypes' => $this->draftSelectedPolicyTypes,
            'draftSelectedStates' => $this->draftSelectedStates,
            'draftSelectedSeverities' => $this->draftSelectedSeverities,
            'draftTenantSort' => $this->draftTenantSort,
            'draftSubjectSort' => $this->draftSubjectSort,
        ];
    }

    /**
     * @return array<string, string>
     */
    private function matrixOptions(string $key): array
    {
        $options = $this->matrix[$key] ?? null;

        return is_array($options) ? $options : [];
    }

    /**
     * @return array{
     *     selectedPolicyTypes: list<string>,
     *     selectedStates: list<string>,
     *     selectedSeverities: list<string>,
     *     tenantSort: string,
     *     subjectSort: string
     * }
     */
    private function draftFilterState(): array
    {
        return [
            'selectedPolicyTypes' => $this->normalizeQueryList($this->draftSelectedPolicyTypes),
            'selectedStates' => $this->normalizeQueryList($this->draftSelectedStates),
            'selectedSeverities' => $this->normalizeQueryList($this->draftSelectedSeverities),
            'tenantSort' => $this->normalizeTenantSort($this->draftTenantSort),
            'subjectSort' => $this->normalizeSubjectSort($this->draftSubjectSort),
        ];
    }

    /**
     * @return array{
     *     selectedPolicyTypes: list<string>,
     *     selectedStates: list<string>,
     *     selectedSeverities: list<string>,
     *     tenantSort: string,
     *     subjectSort: string
     * }
     */
    private function appliedFilterState(): array
    {
        return [
            'selectedPolicyTypes' => $this->selectedPolicyTypes,
            'selectedStates' => $this->selectedStates,
            'selectedSeverities' => $this->selectedSeverities,
            'tenantSort' => $this->tenantSort,
            'subjectSort' => $this->subjectSort,
        ];
    }

    /**
     * @return list<string>
     */
    private function normalizeQueryList(mixed $value): array
    {
        $values = is_array($value) ? $value : [$value];

        return array_values(array_unique(array_filter(array_map(static function (mixed $item): ?string {
            if (! is_string($item)) {
                return null;
            }

            $normalized = trim($item);

            return $normalized !== '' ? $normalized : null;
        }, $values))));
    }

    private function normalizeRequestedMode(mixed $value): string
    {
        return in_array((string) $value, ['auto', 'dense', 'compact'], true)
            ? (string) $value
            : 'auto';
    }

    private function normalizeTenantSort(mixed $value): string
    {
        return in_array((string) $value, ['tenant_name', 'deviation_count', 'freshness_urgency'], true)
            ? (string) $value
            : 'tenant_name';
    }

    private function normalizeSubjectSort(mixed $value): string
    {
        return in_array((string) $value, ['deviation_breadth', 'policy_type', 'display_name'], true)
            ? (string) $value
            : 'deviation_breadth';
    }

    private function compareAssignedTenantsDisabledReason(): ?string
    {
        $reference = is_array($this->matrix['reference'] ?? null) ? $this->matrix['reference'] : [];

        if (($reference['referenceState'] ?? null) !== 'ready') {
            return 'Capture a complete baseline snapshot before comparing assigned environments.';
        }

        if ((int) ($reference['visibleTenantCount'] ?? 0) === 0) {
            return 'No visible assigned environments are available for compare.';
        }

        return $this->compareStartReasonMessage($this->compareAssignedTenantsReasonCode());
    }

    private function compareAssignedTenantsReasonCode(): ?string
    {
        try {
            $scope = $this->getRecord()->normalizedScope();
        } catch (\Throwable) {
            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;
        }

        return null;
    }

    private function compareStartReasonMessage(?string $reasonCode): ?string
    {
        return match ($reasonCode) {
            BaselineReasonCodes::COMPARE_INVALID_SCOPE => 'The assigned baseline scope is invalid and must be reviewed before comparing assigned environments.',
            BaselineReasonCodes::COMPARE_UNSUPPORTED_SCOPE => 'The selected governed subjects are not supported by any compare strategy yet.',
            BaselineReasonCodes::COMPARE_MIXED_SCOPE => 'The selected governed subjects span multiple compare strategy families and must be narrowed before comparing assigned environments.',
            'tenant_sync_required' => 'You need environment sync access for each visible environment before compare can start.',
            default => null,
        };
    }

    private function compareAssignedTenants(): void
    {
        $user = auth()->user();

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

        /** @var BaselineProfile $profile */
        $profile = $this->getRecord();

        $result = app(BaselineCompareService::class)->startCompareForVisibleAssignments($profile, $user);
        $summary = sprintf(
            '%d queued, %d already queued, %d blocked across %d visible assigned tenant%s.',
            (int) $result['queuedCount'],
            (int) $result['alreadyQueuedCount'],
            (int) $result['blockedCount'],
            (int) $result['visibleAssignedTenantCount'],
            (int) $result['visibleAssignedTenantCount'] === 1 ? '' : 's',
        );
        $blockedReasonCodes = collect($result['targets'])
            ->where('launchState', 'blocked')
            ->pluck('reasonCode')
            ->filter(static fn (mixed $reasonCode): bool => is_string($reasonCode) && trim($reasonCode) !== '')
            ->unique()
            ->values();
        $blockedReasonMessage = $blockedReasonCodes->count() === 1
            ? $this->compareStartReasonMessage((string) $blockedReasonCodes->first())
            : null;

        if ((int) $result['queuedCount'] > 0 || (int) $result['alreadyQueuedCount'] > 0) {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);

            $toast = (int) $result['queuedCount'] > 0
                ? OperationUxPresenter::queuedToast(OperationRunType::BaselineCompare->value)
                : OperationUxPresenter::alreadyQueuedToast(OperationRunType::BaselineCompare->value);

            $toast
                ->body($summary.' Open Operations for progress and next steps.')
                ->actions([
                    Action::make('open_operations')
                        ->label('Open operations')
                        ->url(OperationRunLinks::index(
                            context: $this->navigationContext(),
                            allTenants: true,
                        )),
                ])
                ->send();
        } else {
            Notification::make()
                ->title('No baseline compares were started')
                ->body($blockedReasonMessage !== null ? $blockedReasonMessage.' '.$summary : $summary)
                ->warning()
                ->send();
        }

        $this->refreshMatrix();
    }

    /**
     * @param  array<string, mixed>  $overrides
     * @return array<string, mixed>
     */
    private function routeParameters(array $overrides = []): array
    {
        return array_filter([
            'record' => $this->getRecord(),
            'mode' => $this->requestedMode !== 'auto' ? $this->requestedMode : null,
            'policy_type' => $this->selectedPolicyTypes,
            'state' => $this->selectedStates,
            'severity' => $this->selectedSeverities,
            'tenant_sort' => $this->tenantSort !== 'tenant_name' ? $this->tenantSort : null,
            'subject_sort' => $this->subjectSort !== 'deviation_breadth' ? $this->subjectSort : null,
            'subject_key' => $this->focusedSubjectKey,
            ...$overrides,
        ], static fn (mixed $value): bool => $value !== null && $value !== [] && $value !== '');
    }

    private function navigationContext(?ManagedEnvironment $tenant = null, ?string $subjectKey = null): CanonicalNavigationContext
    {
        /** @var BaselineProfile $profile */
        $profile = $this->getRecord();

        $subjectKey ??= $this->focusedSubjectKey;

        return CanonicalNavigationContext::forBaselineCompareMatrix(
            profile: $profile,
            filters: $this->routeParameters(),
            tenant: $tenant,
            subjectKey: $subjectKey,
        );
    }

    private function tenant(int $tenantId): ?ManagedEnvironment
    {
        return ManagedEnvironment::query()
            ->whereKey($tenantId)
            ->where('workspace_id', (int) $this->getRecord()->workspace_id)
            ->first();
    }

    private function workspace(): ?Workspace
    {
        return Workspace::query()->whereKey((int) $this->getRecord()->workspace_id)->first();
    }

    /**
     * @return array<string, mixed>
     */
    private function presentationState(): array
    {
        $resolvedMode = $this->resolvePresentationMode($this->visibleTenantCount());

        return [
            'requestedMode' => $this->requestedMode,
            'resolvedMode' => $resolvedMode,
            'visibleTenantCount' => $this->visibleTenantCount(),
            'activeFilterCount' => $this->activeFilterCount(),
            'hasStagedFilterChanges' => $this->hasStagedFilterChanges(),
            'autoRefreshActive' => (bool) ($this->matrix['hasActiveRuns'] ?? false),
            'lastUpdatedAt' => $this->matrix['lastUpdatedAt'] ?? null,
            'canOverrideMode' => $this->visibleTenantCount() > 0,
            'compactModeAvailable' => $this->canUseCompactMode(),
        ];
    }

    private function visibleTenantCount(): int
    {
        $reference = is_array($this->matrix['reference'] ?? null) ? $this->matrix['reference'] : [];

        return (int) ($reference['visibleTenantCount'] ?? 0);
    }

    private function resolvePresentationMode(int $visibleTenantCount): string
    {
        if ($this->requestedMode === 'dense') {
            return 'dense';
        }

        if ($this->requestedMode === 'compact' && $visibleTenantCount <= 1) {
            return 'compact';
        }

        return $visibleTenantCount > 1 ? 'dense' : 'compact';
    }
}
