<?php

declare(strict_types=1);

namespace App\Filament\Pages\Workspaces;

use App\Exceptions\Onboarding\OnboardingDraftConflictException;
use App\Exceptions\Onboarding\OnboardingDraftImmutableException;
use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Support\VerificationReportChangeIndicator;
use App\Filament\Support\VerificationReportViewer;
use App\Jobs\ProviderComplianceSnapshotJob;
use App\Jobs\ProviderConnectionHealthCheckJob;
use App\Jobs\ProviderInventorySyncJob;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\User;
use App\Models\VerificationCheckAcknowledgement;
use App\Models\Workspace;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Auth\ManagedEnvironmentMembershipManager;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Intune\AuditLogger;
use App\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilder;
use App\Services\Onboarding\OnboardingDraftMutationService;
use App\Services\Onboarding\OnboardingDraftResolver;
use App\Services\Onboarding\OnboardingDraftStageResolver;
use App\Services\Onboarding\OnboardingLifecycleService;
use App\Services\Providers\ProviderConnectionMutationService;
use App\Services\Providers\ProviderOperationRegistry;
use App\Services\Providers\ProviderOperationStartGate;
use App\Services\Tenants\TenantOperabilityService;
use App\Services\Verification\VerificationCheckAcknowledgementService;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Links\RequiredPermissionsLinks;
use App\Support\Livewire\TrustedState\TrustedStateResolver;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Onboarding\OnboardingCheckpoint;
use App\Support\Onboarding\OnboardingDraftStage;
use App\Support\Onboarding\OnboardingLifecycleState;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
use App\Support\ProductKnowledge\ContextualHelpResolver;
use App\Support\Providers\ProviderConnectionType;
use App\Support\Providers\ProviderConsentStatus;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Providers\ProviderVerificationStatus;
use App\Support\Providers\TargetScope\ProviderConnectionSurfaceSummary;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeDescriptor;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeNormalizer;
use App\Support\Tenants\TenantInteractionLane;
use App\Support\Tenants\TenantLifecyclePresentation;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\Verification\VerificationAssistViewModelBuilder;
use App\Support\Verification\VerificationCheckStatus;
use App\Support\Verification\VerificationReportOverall;
use App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Radio;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\ViewField;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Actions as SchemaActions;
use Filament\Schemas\Components\Callout;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Text;
use Filament\Schemas\Components\UnorderedList;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\View as SchemaView;
use Filament\Schemas\Components\Wizard;
use Filament\Schemas\Components\Wizard\Step;
use Filament\Schemas\Schema;
use Filament\Support\Enums\FontWeight;
use Filament\Support\Enums\Width;
use Filament\Support\Exceptions\Halt;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use InvalidArgumentException;
use Livewire\Attributes\Locked;
use RuntimeException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ManagedEnvironmentOnboardingWizard extends Page
{
    use AuthorizesRequests;

    protected static string $layout = 'filament-panels::components.layout.simple';

    protected Width|string|null $maxContentWidth = Width::ScreenExtraLarge;

    protected static bool $shouldRegisterNavigation = false;

    protected static bool $isDiscovered = false;

    protected static ?string $title = 'Managed environment onboarding';

    protected static ?string $slug = 'onboarding';

    /**
     * Disable the simple-layout topbar to prevent lazy-loaded
     * DatabaseNotifications from triggering Livewire update 404s
     * on this workspace-scoped route.
     */
    protected function getLayoutData(): array
    {
        return [
            'hasTopbar' => false,
        ];
    }

    public Workspace $workspace;

    public ?ManagedEnvironment $managedEnvironment = null;

    #[Locked]
    public ?int $managedEnvironmentId = null;

    public ?ManagedEnvironmentOnboardingSession $onboardingSession = null;

    #[Locked]
    public ?int $onboardingSessionId = null;

    public ?int $onboardingSessionVersion = null;

    public ?int $selectedProviderConnectionId = null;

    public bool $showDraftPicker = false;

    public bool $showStartState = false;

    /**
     * Filament schema state.
     *
     * @var array<string, mixed>
     */
    public array $data = [];

    /**
     * @var array<int, string>
     */
    public array $selectedBootstrapOperationTypes = [];

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        $actions = [];
        $draft = $this->currentOnboardingSessionRecord();
        $tenant = $this->currentManagedEnvironmentRecord();

        if (isset($this->workspace)) {
            $actions[] = Action::make('back_to_workspace')
                ->label('Back to workspace')
                ->color('gray')
                ->url(route('admin.home'));
        }

        if ($this->shouldShowDraftLandingAction()) {
            $actions[] = Action::make('back_to_onboarding_landing')
                ->label($this->onboardingDraftLandingActionLabel())
                ->color('gray')
                ->url(route('admin.onboarding'));
        }

        if ($this->canViewLinkedEnvironment()) {
            $actions[] = Action::make('view_linked_environment')
                ->label($this->linkedEnvironmentActionLabel())
                ->color('gray')
                ->url($tenant instanceof ManagedEnvironment ? ManagedEnvironmentLinks::viewUrl($tenant) : null);
        }

        if ($this->canResumeDraft($draft)) {
            $actions[] = Action::make('cancel_onboarding_draft')
                ->label('Cancel draft')
                ->color('danger')
                ->requiresConfirmation()
                ->modalHeading('Cancel onboarding draft')
                ->modalDescription('This draft will become non-resumable. Confirm only if you intend to stop this onboarding flow.')
                ->visible(fn (): bool => $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CANCEL))
                ->action(fn () => $this->cancelOnboardingDraft());
        }

        if ($this->canDeleteDraft($draft)) {
            $actions[] = Action::make('delete_onboarding_draft_header')
                ->label('Delete draft')
                ->color('danger')
                ->requiresConfirmation()
                ->modalHeading('Delete onboarding draft')
                ->modalDescription('This permanently deletes the onboarding draft record. The linked environment record, if any, is not deleted.')
                ->modalSubmitActionLabel('Delete draft')
                ->visible(fn (): bool => $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CANCEL))
                ->action(fn () => $this->deleteOnboardingDraft());
        }

        return $actions;
    }

    private function canViewLinkedEnvironment(): bool
    {
        $user = auth()->user();
        $tenant = $this->currentManagedEnvironmentRecord();

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

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

        return app(TenantOperabilityService::class)->outcomeFor(
            tenant: $tenant,
            question: TenantOperabilityQuestion::EnvironmentBoundViewability,
            actor: $user,
            workspaceId: (int) $this->workspace->getKey(),
            lane: TenantInteractionLane::AdministrativeManagement,
        )->allowed;
    }

    private function linkedEnvironmentActionLabel(): string
    {
        $tenant = $this->currentManagedEnvironmentRecord();

        if (! $tenant instanceof ManagedEnvironment) {
            return 'View environment';
        }

        return sprintf(
            'View environment (%s)',
            TenantLifecyclePresentation::fromTenant($tenant)->label,
        );
    }

    public function mount(ManagedEnvironmentOnboardingSession|int|string|null $onboardingDraft = null): void
    {
        $user = auth()->user();

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

        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if ($workspaceId === null) {
            if ($onboardingDraft !== null) {
                abort(404);
            }

            $this->redirect('/admin/choose-workspace');

            return;
        }

        $workspace = Workspace::query()->whereKey($workspaceId)->first();

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

        if (! app(WorkspaceContext::class)->isMember($user, $workspace)) {
            abort(404);
        }

        $this->workspace = $workspace;

        $this->authorize('viewAny', ManagedEnvironmentOnboardingSession::class);

        if ($onboardingDraft !== null) {
            $this->loadOnboardingDraft($user, $onboardingDraft);
            $this->initializeWizardData();

            return;
        }

        if ($this->resolveLandingState($user)) {
            return;
        }

        $this->showStartState = true;
        $this->initializeWizardData();
    }

    public function content(Schema $schema): Schema
    {
        if ($this->showDraftPicker) {
            return $schema->schema($this->draftPickerSchema());
        }

        if ($this->showsNonResumableSummary()) {
            return $schema->schema($this->nonResumableSummarySchema());
        }

        return $schema
            ->statePath('data')
            ->schema([
                SchemaView::make('filament.schemas.components.managed-environment-onboarding-checkpoint-poll')
                    ->visible(fn (): bool => $this->shouldPollCheckpointLifecycle()),
                ...$this->resumeContextSchema(),
                ...$this->routeBoundReadinessSchema(),
                Wizard::make([
                    Step::make('Identify managed environment')
                        ->description('Create or resume a managed environment in this workspace.')
                        ->schema([
                            Section::make('Managed environment')
                                ->schema([
                                    TextInput::make('entra_tenant_id')
                                        ->label('Entra tenant ID (GUID)')
                                        ->required()
                                        ->placeholder('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')
                                        ->rules(['uuid'])
                                        ->maxLength(255),
                                    Select::make('environment')
                                        ->label('Environment')
                                        ->required()
                                        ->options([
                                            'prod' => 'Production',
                                            'staging' => 'Staging',
                                            'dev' => 'Development',
                                            'other' => 'Other',
                                        ])
                                        ->default('other'),
                                    TextInput::make('name')
                                        ->label('Display name')
                                        ->required()
                                        ->maxLength(255),
                                    TextInput::make('primary_domain')
                                        ->label('Primary domain (optional)')
                                        ->maxLength(255),
                                    Textarea::make('notes')
                                        ->label('Notes (optional)')
                                        ->rows(3)
                                        ->maxLength(2000),
                                ]),
                        ])
                        ->afterValidation(function (): void {
                            $entraTenantId = (string) ($this->data['entra_tenant_id'] ?? '');
                            $environment = (string) ($this->data['environment'] ?? 'other');
                            $environmentName = (string) ($this->data['name'] ?? '');
                            $primaryDomain = (string) ($this->data['primary_domain'] ?? '');
                            $notes = (string) ($this->data['notes'] ?? '');

                            try {
                                $this->identifyManagedEnvironment([
                                    'entra_tenant_id' => $entraTenantId,
                                    'environment' => $environment,
                                    'name' => $environmentName,
                                    'primary_domain' => $primaryDomain,
                                    'notes' => $notes,
                                ]);
                            } catch (NotFoundHttpException) {
                                Notification::make()
                                    ->title('ManagedEnvironment not available')
                                    ->body('This environment cannot be onboarded in this workspace.')
                                    ->danger()
                                    ->send();

                                throw new Halt;
                            }

                            $this->initializeWizardData();
                        }),

                    Step::make('Provider connection')
                        ->description('Select an existing connection or create a new one.')
                        ->schema([
                            Section::make('Connection')
                                ->schema([
                                    Radio::make('connection_mode')
                                        ->label('Mode')
                                        ->options([
                                            'existing' => 'Use existing connection',
                                            'new' => 'Create new connection',
                                        ])
                                        ->required()
                                        ->default('existing')
                                        ->live(),
                                    Select::make('provider_connection_id')
                                        ->label('Provider connection')
                                        ->required(fn (Get $get): bool => $get('connection_mode') === 'existing')
                                        ->options(fn (): array => $this->providerConnectionOptions())
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'existing')
                                        ->hintActions([
                                            Action::make('edit_selected_connection')
                                                ->label('Edit selected connection')
                                                ->icon('heroicon-m-pencil-square')
                                                ->color('gray')
                                                ->slideOver()
                                                ->modalHeading('Edit provider connection')
                                                ->modalDescription('Changes apply to this workspace connection.')
                                                ->modalSubmitActionLabel('Save changes')
                                                ->closeModalByClickingAway(false)
                                                ->visible(fn (Get $get): bool => $get('connection_mode') === 'existing'
                                                    && is_numeric($get('provider_connection_id')))
                                                ->disabled(fn (): bool => ! $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE))
                                                ->tooltip(fn (): ?string => $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE)
                                                    ? null
                                                    : 'You don\'t have permission to edit connections.')
                                                ->fillForm(function (Get $get): array {
                                                    $recordId = $get('provider_connection_id');

                                                    if (! is_numeric($recordId)) {
                                                        return [];
                                                    }

                                                    return $this->inlineEditSelectedConnectionFill((int) $recordId);
                                                })
                                                ->form([
                                                    TextInput::make('display_name')
                                                        ->label('Connection name')
                                                        ->required()
                                                        ->maxLength(255),
                                                    TextInput::make('entra_tenant_id')
                                                        ->label('Target scope ID')
                                                        ->helperText('Provider-owned Microsoft tenant detail for this selected target scope.')
                                                        ->disabled()
                                                        ->dehydrated(false),
                                                    Toggle::make('uses_dedicated_override')
                                                        ->label('Dedicated override')
                                                        ->helperText('Explicit exception path for a customer-managed app registration.')
                                                        ->visible(fn (): bool => $this->canManageDedicatedOverride())
                                                        ->live(),
                                                    TextInput::make('client_id')
                                                        ->label('Dedicated app (client) ID')
                                                        ->required(fn (Get $get): bool => (bool) $get('uses_dedicated_override'))
                                                        ->maxLength(255)
                                                        ->helperText('If you change the dedicated App (client) ID, enter the matching new client secret below.')
                                                        ->visible(fn (Get $get): bool => (bool) $get('uses_dedicated_override')),
                                                    TextInput::make('client_secret')
                                                        ->label('New dedicated client secret')
                                                        ->password()
                                                        ->revealable(false)
                                                        ->maxLength(255)
                                                        ->helperText('Required when enabling dedicated mode or changing the dedicated App (client) ID. The existing secret is never shown.')
                                                        ->visible(fn (Get $get): bool => (bool) $get('uses_dedicated_override')),
                                                ])
                                                ->action(function (array $data, Get $get): void {
                                                    $recordId = $get('provider_connection_id');

                                                    if (! is_numeric($recordId)) {
                                                        abort(404);
                                                    }

                                                    $this->updateSelectedProviderConnectionInline((int) $recordId, $data);
                                                }),
                                        ]),

                                    TextInput::make('new_connection.display_name')
                                        ->label('Display name')
                                        ->required(fn (Get $get): bool => $get('connection_mode') === 'new')
                                        ->maxLength(255)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new'),
                                    TextInput::make('new_connection.target_scope_id')
                                        ->label('Target scope ID')
                                        ->default(fn (): string => $this->currentManagedEnvironmentRecord()?->managed_environment_id ?? '')
                                        ->disabled()
                                        ->dehydrated(false)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new')
                                        ->helperText('The provider connection will point to this tenant target scope.'),
                                    TextInput::make('new_connection.connection_type')
                                        ->label('Connection type')
                                        ->default('Platform connection')
                                        ->disabled()
                                        ->dehydrated(false)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new')
                                        ->helperText('Managed centrally by platform. Grant admin consent after creating the connection.'),
                                    TextInput::make('new_connection.platform_app_id')
                                        ->label('Platform app ID')
                                        ->default(fn (): string => $this->platformAppClientId())
                                        ->disabled()
                                        ->dehydrated(false)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new'),
                                    Toggle::make('new_connection.uses_dedicated_override')
                                        ->label('Dedicated override')
                                        ->helperText('Explicit exception path for a customer-managed app registration.')
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new' && $this->canManageDedicatedOverride())
                                        ->live(),
                                    TextInput::make('new_connection.client_id')
                                        ->label('Dedicated app (client) ID')
                                        ->required(fn (Get $get): bool => $get('connection_mode') === 'new' && (bool) $get('new_connection.uses_dedicated_override'))
                                        ->maxLength(255)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new' && (bool) $get('new_connection.uses_dedicated_override')),
                                    TextInput::make('new_connection.client_secret')
                                        ->label('Dedicated client secret')
                                        ->password()
                                        ->revealable(false)
                                        ->required(fn (Get $get): bool => $get('connection_mode') === 'new' && (bool) $get('new_connection.uses_dedicated_override'))
                                        ->maxLength(255)
                                        ->helperText('Required only for the dedicated override path. The secret is never shown again after save.')
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new' && (bool) $get('new_connection.uses_dedicated_override')),
                                    Toggle::make('new_connection.is_default')
                                        ->label('Make default')
                                        ->default(true)
                                        ->visible(fn (Get $get): bool => $get('connection_mode') === 'new'),
                                ]),
                        ])
                        ->afterValidation(function (): void {
                            if (! $this->managedEnvironment instanceof ManagedEnvironment) {
                                throw new Halt;
                            }

                            $mode = (string) ($this->data['connection_mode'] ?? 'existing');

                            if ($mode === 'new') {
                                $new = is_array($this->data['new_connection'] ?? null) ? $this->data['new_connection'] : [];

                                $this->createProviderConnection([
                                    'display_name' => (string) ($new['display_name'] ?? ''),
                                    'connection_type' => (bool) ($new['uses_dedicated_override'] ?? false)
                                        ? ProviderConnectionType::Dedicated->value
                                        : ProviderConnectionType::Platform->value,
                                    'client_id' => (string) ($new['client_id'] ?? ''),
                                    'client_secret' => (string) ($new['client_secret'] ?? ''),
                                    'is_default' => (bool) ($new['is_default'] ?? true),
                                ]);
                            } else {
                                $providerConnectionId = (int) ($this->data['provider_connection_id'] ?? 0);

                                if ($providerConnectionId <= 0) {
                                    throw new Halt;
                                }

                                $this->selectProviderConnection($providerConnectionId);
                            }

                            $this->touchOnboardingSessionStep('connection');
                            $this->initializeWizardData();
                        }),

                    Step::make('Verify access')
                        ->description('Run a queued verification check (Operation).')
                        ->schema([
                            Section::make('Verification')
                                ->schema([
                                    Text::make(fn (): string => 'Status: '.$this->verificationStatusLabel())
                                        ->badge()
                                        ->color(fn (): string => $this->verificationStatusColor()),
                                    Text::make('Connection updated — re-run verification to refresh results.')
                                        ->visible(fn (): bool => $this->connectionRecentlyUpdated()),
                                    Text::make('The selected provider connection has changed since this verification operation. Start verification again to validate the current connection.')
                                        ->visible(fn (): bool => $this->verificationRunIsStaleForSelectedConnection()),
                                    Text::make('Verification is in progress. Status updates automatically about every 5 seconds. Use “Refresh” to re-check immediately.')
                                        ->visible(fn (): bool => $this->verificationStatus() === 'in_progress'),
                                    SchemaActions::make([
                                        Action::make('wizardStartVerification')
                                            ->label('Start verification')
                                            ->visible(fn (): bool => $this->managedEnvironment instanceof ManagedEnvironment && ! $this->verificationRunIsActive())
                                            ->disabled(fn (): bool => ! $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_VERIFICATION_START))
                                            ->tooltip(fn (): ?string => $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_VERIFICATION_START)
                                                ? null
                                                : 'You do not have permission to start verification.')
                                            ->action(fn () => $this->startVerification()),
                                        Action::make('wizardRefreshVerification')
                                            ->label('Refresh')
                                            ->visible(fn (): bool => $this->verificationRunUrl() !== null && $this->verificationStatus() === 'in_progress')
                                            ->action(fn () => $this->refreshVerificationStatus()),
                                    ]),
                                    ViewField::make('verification_report')
                                        ->label('')
                                        ->default(null)
                                        ->view('filament.forms.components.managed-environment-onboarding-verification-report')
                                        ->viewData(fn (): array => $this->verificationReportViewData())
                                        ->visible(fn (): bool => $this->managedEnvironment instanceof ManagedEnvironment),
                                ]),
                        ])
                        ->beforeValidation(function (): void {
                            if (! $this->verificationCanProceed()) {
                                Notification::make()
                                    ->title('Verification required')
                                    ->body('Complete verification for the selected provider connection before continuing.')
                                    ->warning()
                                    ->send();

                                throw new Halt;
                            }

                            $this->touchOnboardingSessionStep('verify');
                        }),

                    Step::make('Bootstrap (optional)')
                        ->description('Optionally start inventory and compliance operations.')
                        ->schema([
                            Section::make('Bootstrap')
                                ->schema([
                                    CheckboxList::make('bootstrap_operation_types')
                                        ->label('Bootstrap actions')
                                        ->options(fn (): array => $this->bootstrapOperationOptions())
                                        ->columns(1),
                                    SchemaActions::make([
                                        Action::make('wizardStartBootstrap')
                                            ->label('Start bootstrap')
                                            ->visible(fn (): bool => $this->managedEnvironment instanceof ManagedEnvironment)
                                            ->disabled(fn (): bool => ! $this->canStartAnyBootstrap())
                                            ->tooltip(fn (): ?string => $this->canStartAnyBootstrap()
                                                ? null
                                                : 'You do not have permission to start bootstrap actions.')
                                            ->action(fn (Get $get) => $this->startBootstrap(
                                                $this->normalizeBootstrapOperationTypes((array) ($get('bootstrap_operation_types') ?? [])),
                                            )),
                                    ]),
                                    Text::make(fn (): string => $this->bootstrapRunsLabel())
                                        ->hidden(fn (): bool => $this->bootstrapRunsLabel() === ''),
                                ]),
                        ])
                        ->afterValidation(function (): void {
                            $types = $this->data['bootstrap_operation_types'] ?? [];
                            $this->selectedBootstrapOperationTypes = $this->normalizeBootstrapOperationTypes(
                                is_array($types) ? $types : [],
                            );

                            $this->persistBootstrapSelection($this->selectedBootstrapOperationTypes);

                            $this->touchOnboardingSessionStep('bootstrap');
                        }),

                    Step::make('Complete')
                        ->description('Review configuration and complete onboarding for this environment.')
                        ->schema([
                            Section::make('Review & Complete onboarding')
                                ->description('Review the onboarding summary before completing onboarding for this environment.')
                                ->schema([
                                    Section::make('Onboarding summary')
                                        ->compact()
                                        ->columns(2)
                                        ->schema([
                                            Text::make('Managed environment')
                                                ->color('gray'),
                                            Text::make(fn (): string => $this->completionSummaryEnvironmentLine())
                                                ->weight(FontWeight::SemiBold),
                                            Text::make('Provider connection')
                                                ->color('gray'),
                                            Text::make(fn (): string => $this->completionSummaryConnectionSummary())
                                                ->weight(FontWeight::SemiBold),
                                            Text::make('Verification')
                                                ->color('gray'),
                                            Text::make(fn (): string => $this->verificationStatusLabel().' — '.$this->completionSummaryVerificationDetail())
                                                ->badge()
                                                ->color(fn (): string => $this->verificationStatusColor()),
                                            Text::make('Bootstrap')
                                                ->color('gray'),
                                            Text::make(fn (): string => $this->completionSummaryBootstrapSummary())
                                                ->badge()
                                                ->color(fn (): string => $this->completionSummaryBootstrapColor()),
                                            Text::make('Activation entitlement')
                                                ->color('gray'),
                                            Text::make(fn (): string => $this->completionSummaryEntitlementSummary())
                                                ->badge()
                                                ->color(fn (): string => $this->completionSummaryEntitlementColor()),
                                        ]),
                                    Callout::make('Activation entitlement')
                                        ->description(fn (): string => $this->completionSummaryEntitlementDetail())
                                        ->warning()
                                        ->visible(fn (): bool => $this->completionSummaryEntitlementBlocked()),
                                    Callout::make('Bootstrap needs attention')
                                        ->description(fn (): string => $this->completionSummaryBootstrapRecoveryMessage())
                                        ->warning()
                                        ->visible(fn (): bool => $this->showCompletionSummaryBootstrapRecovery()),
                                    Callout::make('After completion')
                                        ->description('This action is recorded in the audit log and cannot be undone from this wizard.')
                                        ->info()
                                        ->footer([
                                            UnorderedList::make([
                                                'ManagedEnvironment status will be set to Active.',
                                                'Backup, inventory, and compliance operations become available.',
                                                'The provider connection will be used for provider API calls.',
                                            ]),
                                        ]),
                                    Toggle::make('override_blocked')
                                        ->label('Override blocked verification')
                                        ->helperText('Owner-only. Requires a reason and will be recorded in the audit log.')
                                        ->visible(fn (): bool => $this->verificationStatus() === 'blocked'
                                            && $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_ACTIVATE)),
                                    Textarea::make('override_reason')
                                        ->label('Override reason')
                                        ->required(fn (Get $get): bool => (bool) $get('override_blocked'))
                                        ->visible(fn (Get $get): bool => (bool) $get('override_blocked'))
                                        ->rows(3)
                                        ->maxLength(500),
                                    SchemaActions::make([
                                        Action::make('wizardCompleteOnboarding')
                                            ->label('Complete onboarding')
                                            ->color('success')
                                            ->requiresConfirmation()
                                            ->modalHeading('Complete onboarding')
                                            ->modalDescription(fn (): string => $this->managedEnvironment instanceof ManagedEnvironment
                                                ? sprintf('Are you sure you want to complete onboarding for "%s"? This will make the environment operational.', $this->managedEnvironment->name)
                                                : 'Are you sure you want to complete onboarding for this environment?')
                                            ->modalSubmitActionLabel('Yes, complete onboarding')
                                            ->disabled(fn (): bool => ! $this->canCompleteOnboarding()
                                                || ! $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_ACTIVATE))
                                            ->tooltip(fn (): ?string => $this->completionActionTooltip())
                                            ->action(fn () => $this->completeOnboarding()),
                                    ]),
                                ]),
                        ])
                        ->beforeValidation(function (): void {
                            if (! $this->canCompleteOnboarding()) {
                                throw new Halt;
                            }
                        }),
                ])
                    ->startOnStep(fn (): int => $this->computeWizardStartStep())
                    ->skippable(false),
            ]);
    }

    private function resolveLandingState(User $user): bool
    {
        $drafts = $this->availableDraftsFor($user);

        if ($drafts->count() === 1) {
            $draft = $drafts->first();

            if ($draft instanceof ManagedEnvironmentOnboardingSession) {
                $this->redirect(route('admin.onboarding.draft', ['onboardingDraft' => $draft]));

                return true;
            }
        }

        if ($drafts->count() > 1) {
            $this->showDraftPicker = true;
        }

        return false;
    }

    private function loadOnboardingDraft(User $user, ManagedEnvironmentOnboardingSession|int|string $onboardingDraft): void
    {
        $draft = app(OnboardingDraftResolver::class)->resolve($onboardingDraft, $user, $this->workspace);

        $this->showDraftPicker = false;
        $this->showStartState = false;
        $this->setOnboardingSession($draft);

        $tenant = $draft->managedEnvironment;

        if ($tenant instanceof ManagedEnvironment && (int) $tenant->workspace_id === (int) $this->workspace->getKey()) {
            $this->setManagedEnvironment($tenant);
        }

        $providerConnectionId = $draft->state['provider_connection_id'] ?? null;
        $this->selectedProviderConnectionId = $this->resolvePersistedProviderConnectionId($providerConnectionId);

        $bootstrapTypes = $draft->state['bootstrap_operation_types'] ?? [];
        $this->selectedBootstrapOperationTypes = is_array($bootstrapTypes)
            ? $this->normalizeBootstrapOperationTypes($bootstrapTypes)
            : [];
    }

    /**
     * @param  array<int|string, mixed>  $operationTypes
     * @return array<int, string>
     */
    private function normalizeBootstrapOperationTypes(array $operationTypes): array
    {
        $supportedTypes = array_keys($this->supportedBootstrapCapabilities());
        $normalized = [];

        foreach ($operationTypes as $key => $value) {
            if (is_string($value)) {
                $normalizedValue = $this->normalizeBootstrapOperationType($value);

                if ($normalizedValue !== '' && in_array($normalizedValue, $supportedTypes, true)) {
                    $normalized[] = $normalizedValue;
                }

                continue;
            }

            if (! is_string($key) || trim($key) === '') {
                continue;
            }

            $isSelected = match (true) {
                is_bool($value) => $value,
                is_int($value) => $value === 1,
                is_string($value) => in_array(strtolower(trim($value)), ['1', 'true', 'on', 'yes'], true),
                default => false,
            };

            $normalizedKey = $this->normalizeBootstrapOperationType($key);

            if ($isSelected && in_array($normalizedKey, $supportedTypes, true)) {
                $normalized[] = $normalizedKey;
            }
        }

        return array_values(array_unique($normalized));
    }

    private function normalizeBootstrapOperationType(string $operationType): string
    {
        $operationType = trim($operationType);

        if ($operationType === '') {
            return '';
        }

        return OperationCatalog::canonicalCode($operationType);
    }

    /**
     * @return array<string, string>
     */
    private function supportedBootstrapCapabilities(): array
    {
        return [
            'inventory.sync' => Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_BOOTSTRAP_INVENTORY_SYNC,
            'compliance.snapshot' => Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_BOOTSTRAP_POLICY_SYNC,
        ];
    }

    /**
     * @param  array<int, string>  $operationTypes
     */
    private function persistBootstrapSelection(array $operationTypes): void
    {
        $user = auth()->user();

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

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return;
        }

        $normalized = $this->normalizeBootstrapOperationTypes($operationTypes);
        $existing = $this->onboardingSession->state['bootstrap_operation_types'] ?? null;
        $existing = is_array($existing)
            ? $this->normalizeBootstrapOperationTypes($existing)
            : [];

        if ($normalized === $existing) {
            return;
        }

        try {
            $this->setOnboardingSession($this->mutationService()->mutate(
                draft: $this->onboardingSession,
                actor: $user,
                expectedVersion: $this->expectedDraftVersion(),
                incrementVersion: false,
                mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($normalized): void {
                    $state = is_array($draft->state) ? $draft->state : [];
                    $state['bootstrap_operation_types'] = $normalized;

                    $draft->state = $state;
                },
            ));
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict();

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft();

            return;
        }
    }

    /**
     * @return Collection<int, ManagedEnvironmentOnboardingSession>
     */
    private function availableDraftsFor(User $user): Collection
    {
        return app(OnboardingDraftResolver::class)->resumableDraftsFor($user, $this->workspace);
    }

    /**
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function draftPickerSchema(): array
    {
        $drafts = $this->currentUser() instanceof User
            ? $this->availableDraftsFor($this->currentUser())
            : collect();

        $components = [
            Callout::make('Multiple onboarding drafts are available.')
                ->description('Select a draft to resume or start a new onboarding flow explicitly.')
                ->warning(),
            SchemaActions::make([
                Action::make('start_new_onboarding_draft')
                    ->label('Start new onboarding')
                    ->color('primary')
                    ->action(fn () => $this->startNewOnboardingDraft()),
            ])->key('draft_picker_start_actions'),
        ];

        foreach ($drafts as $draft) {
            $components[] = Section::make($this->draftTitle($draft))
                ->description($this->draftDescription($draft))
                ->compact()
                ->columns(2)
                ->schema([
                    Text::make('Current stage')
                        ->color('gray'),
                    Text::make(fn (): string => $this->draftStageLabel($draft))
                        ->badge()
                        ->color(fn (): string => $this->draftStageColor($draft)),
                    Text::make('Status')
                        ->color('gray'),
                    Text::make(fn (): string => $draft->status()->label())
                        ->badge()
                        ->color(fn (): string => $this->draftStatusColor($draft)),
                    Text::make('Started by')
                        ->color('gray'),
                    Text::make(fn (): string => $draft->startedByUser?->name ?? 'Unknown'),
                    Text::make('Last updated by')
                        ->color('gray'),
                    Text::make(fn (): string => $draft->updatedByUser?->name ?? 'Unknown'),
                    Text::make('Last updated')
                        ->color('gray'),
                    Text::make(fn (): string => $draft->updated_at?->diffForHumans() ?? '—'),
                    Text::make('Draft age')
                        ->color('gray'),
                    Text::make(fn (): string => $draft->created_at?->diffForHumans() ?? '—'),
                    ...$this->draftCompactReadinessSchema($draft),
                    SchemaActions::make([
                        Action::make('resume_draft_'.$draft->getKey())
                            ->label($this->resumeOnboardingActionLabel())
                            ->action(fn () => $this->resumeOnboardingDraft((int) $draft->getKey(), true)),
                        Action::make('view_draft_'.$draft->getKey())
                            ->label('View summary')
                            ->color('gray')
                            ->action(fn () => $this->resumeOnboardingDraft((int) $draft->getKey(), false)),
                    ])->key('draft_picker_actions_'.$draft->getKey()),
                ]);
        }

        return $components;
    }

    /**
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function resumeContextSchema(): array
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return [];
        }

        return [
            Section::make('Onboarding draft')
                ->compact()
                ->collapsible()
                ->collapsed()
                ->columns(2)
                ->schema([
                    Text::make('ManagedEnvironment')
                        ->color('gray'),
                    Text::make(fn () => $this->draftTitle($this->currentOnboardingSessionRecord() ?? $draft))
                        ->weight(FontWeight::SemiBold),
                    Text::make('Current stage')
                        ->color('gray'),
                    Text::make(fn () => $this->draftStageLabel($this->currentOnboardingSessionRecord() ?? $draft))
                        ->badge()
                        ->color(fn () => $this->draftStageColor($this->currentOnboardingSessionRecord() ?? $draft)),
                    Text::make('Started by')
                        ->color('gray'),
                    Text::make(fn () => ($this->currentOnboardingSessionRecord() ?? $draft)?->startedByUser?->name ?? 'Unknown'),
                    Text::make('Last updated by')
                        ->color('gray'),
                    Text::make(fn () => ($this->currentOnboardingSessionRecord() ?? $draft)?->updatedByUser?->name ?? 'Unknown'),
                ]),
        ];
    }

    /**
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function routeBoundReadinessSchema(): array
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return [];
        }

        $payload = $this->onboardingReadinessPayload($draft);
        $primaryNextAction = $this->readinessPrimaryNextActionComponent($payload, 'route_bound_readiness');

        $schema = [
            Section::make('Onboarding readiness')
                ->description($payload['blocker']['operator_summary'])
                ->compact()
                ->columns(2)
                ->schema([
                    Text::make('Step')
                        ->color('gray'),
                    Text::make($payload['checkpoint']['current_checkpoint_label'] ?? '—')
                        ->badge()
                        ->color('info'),
                    Text::make('Lifecycle')
                        ->color('gray'),
                    Text::make($payload['checkpoint']['lifecycle_label'])
                        ->badge()
                        ->color($this->readinessLifecycleColor($payload['checkpoint']['lifecycle_state'])),
                    Text::make('Provider connection')
                        ->color('gray'),
                    Text::make($this->readinessProviderLine($payload))
                        ->badge()
                        ->color($this->readinessSummaryColor($payload)),
                    Text::make('Freshness')
                        ->color('gray'),
                    Text::make($payload['freshness']['note']),
                    Text::make('Primary next action')
                        ->color('gray'),
                    $primaryNextAction,
                ]),
        ];

        $permissionDiagnostics = $this->readinessPermissionDiagnosticsSchema($payload, 'route_bound_readiness');
        $supportingEvidence = $this->readinessSupportingEvidenceSchema($payload, 'route_bound_readiness');

        return array_merge($schema, $permissionDiagnostics, $supportingEvidence);
    }

    /**
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function draftCompactReadinessSchema(ManagedEnvironmentOnboardingSession $draft): array
    {
        $payload = $this->onboardingReadinessPayload($draft);

        return [
            Text::make('Compact readiness')
                ->color('gray'),
            Text::make($payload['blocker']['operator_summary'])
                ->badge()
                ->color($this->readinessSummaryColor($payload)),
            Text::make('Freshness')
                ->color('gray'),
            Text::make($payload['freshness']['note']),
            Text::make('Next action')
                ->color('gray'),
            Text::make($payload['next_action']['label'])
                ->badge()
                ->color($this->readinessNextActionColor($payload['next_action']['kind'])),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function readinessSupportingEvidenceSchema(array $payload, string $keyPrefix): array
    {
        $links = is_array($payload['supporting_links'] ?? null) ? $payload['supporting_links'] : [];
        $assist = is_array($payload['verification_assist'] ?? null) ? $payload['verification_assist'] : [];
        $showAssist = (bool) ($assist['is_visible'] ?? false);
        $permissions = is_array($payload['permissions'] ?? null) ? $payload['permissions'] : [];
        $requiredPermissionsUrl = is_string($permissions['required_permissions_url'] ?? null)
            ? $permissions['required_permissions_url']
            : null;

        if ($links === [] && ! ($showAssist && $requiredPermissionsUrl !== null && $requiredPermissionsUrl !== '')) {
            return [];
        }

        $actions = [];

        foreach (array_values($links) as $index => $link) {
            if (! is_array($link)) {
                continue;
            }

            $label = is_string($link['label'] ?? null) ? $link['label'] : OperationRunLinks::openLabel();
            $url = is_string($link['url'] ?? null) ? $link['url'] : null;

            if ($url === null || $url === '') {
                continue;
            }

            $actions[] = Action::make($keyPrefix.'_supporting_operation_'.$index)
                ->label($label)
                ->color('gray')
                ->url($url);
        }

        if ($showAssist && $requiredPermissionsUrl !== null && $requiredPermissionsUrl !== '') {
            $actions[] = Action::make($keyPrefix.'_required_permissions_assist')
                ->label('View required permissions')
                ->color('gray')
                ->url($requiredPermissionsUrl);
        }

        if ($actions === []) {
            return [];
        }

        return [
            Section::make('Supporting evidence')
                ->description('Open canonical operation detail or secondary permission evidence when deeper diagnostics are needed.')
                ->compact()
                ->schema([
                    SchemaActions::make($actions)->key($keyPrefix.'_supporting_evidence_actions'),
                ]),
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function readinessPermissionDiagnosticsSchema(array $payload, string $keyPrefix): array
    {
        $permissions = is_array($payload['permissions'] ?? null) ? $payload['permissions'] : null;

        if ($permissions === null) {
            return [];
        }

        if ((bool) ($payload['verification']['has_report'] ?? false)) {
            return [];
        }

        $counts = is_array($permissions['counts'] ?? null) ? $permissions['counts'] : [];
        $missingApplication = (int) ($counts['missing_application'] ?? 0);
        $missingDelegated = (int) ($counts['missing_delegated'] ?? 0);
        $errors = (int) ($counts['error'] ?? 0);

        if ($missingApplication + $missingDelegated + $errors === 0) {
            return [];
        }

        $schema = [
            Text::make('Primary provider capability')
                ->color('gray'),
            Text::make($this->readinessPrimaryCapabilityLine($permissions))
                ->badge()
                ->color($this->readinessPrimaryCapabilityColor($permissions)),
            Text::make('Missing application permissions')
                ->color('gray'),
            Text::make((string) $missingApplication)
                ->badge()
                ->color($missingApplication > 0 ? 'warning' : 'success'),
            Text::make('Missing delegated permissions')
                ->color('gray'),
            Text::make((string) $missingDelegated)
                ->badge()
                ->color($missingDelegated > 0 ? 'warning' : 'success'),
        ];

        $applicationLine = $this->readinessMissingPermissionLine($permissions, 'application');
        $delegatedLine = $this->readinessMissingPermissionLine($permissions, 'delegated');

        if ($applicationLine !== null) {
            $schema[] = Text::make('Application permission detail')->color('gray');
            $schema[] = Text::make($applicationLine);
        }

        if ($delegatedLine !== null) {
            $schema[] = Text::make('Delegated permission detail')->color('gray');
            $schema[] = Text::make($delegatedLine);
        }

        $url = is_string($permissions['required_permissions_url'] ?? null) ? $permissions['required_permissions_url'] : null;

        if ($url !== null && $url !== '') {
            $schema[] = SchemaActions::make([
                Action::make($keyPrefix.'_review_permissions')
                    ->label('Review permissions')
                    ->color('gray')
                    ->url($url),
            ])->key($keyPrefix.'_permission_diagnostics_actions');
        }

        return [
            Section::make('Permission diagnostics')
                ->description('Provider-owned permission detail stays secondary to readiness while still giving exact remediation context.')
                ->compact()
                ->columns(2)
                ->schema($schema),
        ];
    }

    /**
     * @return array{
     *     draft: array{id: int, environment_name: string, stage_label: string, draft_status_label: string, started_by: string, updated_by: string, last_updated_human: string},
     *     checkpoint: array{current_checkpoint: string|null, current_checkpoint_label: string|null, last_completed_checkpoint: string|null, lifecycle_state: string, lifecycle_label: string},
     *     provider_summary: array<string, mixed>|null,
     *     verification: array{status: string, status_label: string, run_id: int|null, run_url: string|null, is_active: bool, has_report: bool, matches_selected_connection: bool|null, overall: string|null},
     *     verification_assist: array{is_visible: bool, reason: string},
     *     permissions: array{overall: string|null, counts: array<string, int>, freshness: array{last_refreshed_at: string|null, is_stale: bool}, capability_groups: array<int, array<string, mixed>>, primary_capability_group: array<string, mixed>|null, missing_permissions: array{application: list<string>, delegated: list<string>}, required_permissions_url: string|null}|null,
     *     freshness: array{connection_recently_updated: bool, verification_mismatch: bool, permission_last_refreshed_at: string|null, permission_data_is_stale: bool, note: string},
     *     blocker: array{reason_code: string|null, blocking_reason_code: string|null, operator_summary: string},
     *     next_action: array{label: string, kind: string, url: string|null, action_name: string|null, required_capability: string|null},
     *     supporting_links: list<array{label: string, url: string}>
     * }
     */
    private function onboardingReadinessPayload(ManagedEnvironmentOnboardingSession $draft): array
    {
        $snapshot = $this->lifecycleService()->snapshot($draft);
        $stage = app(OnboardingDraftStageResolver::class)->resolve($draft);
        $lifecycleState = $snapshot['lifecycle_state'] instanceof OnboardingLifecycleState
            ? $snapshot['lifecycle_state']
            : OnboardingLifecycleState::Draft;
        $currentCheckpoint = $snapshot['current_checkpoint'] instanceof OnboardingCheckpoint
            ? $snapshot['current_checkpoint']
            : null;
        $lastCompletedCheckpoint = $snapshot['last_completed_checkpoint'] instanceof OnboardingCheckpoint
            ? $snapshot['last_completed_checkpoint']
            : null;

        $tenant = $draft->managedEnvironment instanceof ManagedEnvironment ? $draft->managedEnvironment : null;
        $providerConnection = $this->readinessProviderConnection($draft);
        $selectedProviderConnectionId = $providerConnection instanceof ProviderConnection
            ? (int) $providerConnection->getKey()
            : null;

        $verificationRun = $this->lifecycleService()->verificationRun($draft);
        $verificationStatus = $this->lifecycleService()->verificationStatus(
            draft: $draft,
            selectedProviderConnectionId: $selectedProviderConnectionId,
            run: $verificationRun,
        );
        $verificationMatchesSelectedConnection = $verificationRun instanceof OperationRun
            ? $this->readinessRunMatchesSelectedConnection($verificationRun, $selectedProviderConnectionId)
            : null;
        $permissions = $tenant instanceof ManagedEnvironment ? $this->readinessPermissionOverview($tenant) : null;
        $verificationReport = $verificationRun instanceof OperationRun ? VerificationReportViewer::report($verificationRun) : null;
        $verificationReport = is_array($verificationReport) ? $verificationReport : null;
        $verificationPrimaryReasonCode = $verificationReport !== null
            ? app(ContextualHelpResolver::class)->primaryReasonCodeFromVerificationReport($verificationReport)
            : null;
        $permissionFreshness = is_array($permissions['freshness'] ?? null) ? $permissions['freshness'] : [
            'last_refreshed_at' => null,
            'is_stale' => true,
        ];

        $connectionRecentlyUpdated = $this->readinessConnectionRecentlyUpdated($draft);
        $verificationMismatch = $verificationRun instanceof OperationRun && $verificationMatchesSelectedConnection === false;
        $supportingLinks = $this->readinessSupportingLinks($verificationRun, $draft, $selectedProviderConnectionId);
        $readinessSummary = $this->readinessSummaryText(
            draft: $draft,
            lifecycleState: $lifecycleState,
            providerConnection: $providerConnection,
            verificationRun: $verificationRun,
            verificationStatus: $verificationStatus,
            permissions: $permissions,
            connectionRecentlyUpdated: $connectionRecentlyUpdated,
            verificationMismatch: $verificationMismatch,
        );

        $reasonCode = is_string($snapshot['reason_code'] ?? null) ? $snapshot['reason_code'] : null;
        $blockingReasonCode = is_string($snapshot['blocking_reason_code'] ?? null) ? $snapshot['blocking_reason_code'] : null;

        return [
            'draft' => [
                'id' => (int) $draft->getKey(),
                'environment_name' => $this->draftTitle($draft),
                'stage_label' => $stage->label(),
                'draft_status_label' => $draft->status()->label(),
                'started_by' => $draft->startedByUser?->name ?? 'Unknown',
                'updated_by' => $draft->updatedByUser?->name ?? 'Unknown',
                'last_updated_human' => $draft->updated_at?->diffForHumans() ?? '—',
            ],
            'checkpoint' => [
                'current_checkpoint' => $currentCheckpoint?->value,
                'current_checkpoint_label' => $currentCheckpoint?->label(),
                'last_completed_checkpoint' => $lastCompletedCheckpoint?->label(),
                'lifecycle_state' => $lifecycleState->value,
                'lifecycle_label' => $lifecycleState->label(),
            ],
            'provider_summary' => $this->readinessProviderSummary($providerConnection),
            'verification' => [
                'status' => $verificationStatus,
                'status_label' => BadgeCatalog::spec(BadgeDomain::ManagedEnvironmentOnboardingVerificationStatus, $verificationStatus)->label,
                'run_id' => $verificationRun instanceof OperationRun ? (int) $verificationRun->getKey() : null,
                'run_url' => $verificationRun instanceof OperationRun && $this->canInspectOperationRun($verificationRun)
                    ? OperationRunLinks::tenantlessView($verificationRun)
                    : null,
                'is_active' => $verificationRun instanceof OperationRun && $verificationRun->status !== OperationRunStatus::Completed->value,
                'has_report' => $verificationReport !== null,
                'matches_selected_connection' => $verificationMatchesSelectedConnection,
                'overall' => $verificationRun instanceof OperationRun
                    ? $this->readinessVerificationOverall($verificationRun, $verificationReport)
                    : null,
            ],
            'verification_assist' => $tenant instanceof ManagedEnvironment && $verificationReport !== null
                ? app(VerificationAssistViewModelBuilder::class)->visibility($tenant, $verificationReport)
                : $this->hiddenVerificationAssistVisibility(),
            'permissions' => $permissions,
            'freshness' => [
                'connection_recently_updated' => $connectionRecentlyUpdated,
                'verification_mismatch' => $verificationMismatch,
                'permission_last_refreshed_at' => $permissionFreshness['last_refreshed_at'] ?? null,
                'permission_data_is_stale' => (bool) ($permissionFreshness['is_stale'] ?? true),
                'note' => $this->readinessFreshnessNote(
                    verificationRun: $verificationRun,
                    verificationStatus: $verificationStatus,
                    connectionRecentlyUpdated: $connectionRecentlyUpdated,
                    verificationMismatch: $verificationMismatch,
                    permissionFreshness: $permissionFreshness,
                ),
            ],
            'blocker' => [
                'reason_code' => $reasonCode,
                'blocking_reason_code' => $blockingReasonCode,
                'operator_summary' => $readinessSummary,
            ],
            'next_action' => $this->readinessNextAction(
                draft: $draft,
                lifecycleState: $lifecycleState,
                providerConnection: $providerConnection,
                verificationRun: $verificationRun,
                verificationStatus: $verificationStatus,
                permissions: $permissions,
                blockerReasonCode: $verificationPrimaryReasonCode ?? $blockingReasonCode ?? $reasonCode,
                connectionRecentlyUpdated: $connectionRecentlyUpdated,
                verificationMismatch: $verificationMismatch,
                supportingLinks: $supportingLinks,
            ),
            'supporting_links' => $supportingLinks,
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     */
    private function readinessProviderLine(array $payload): string
    {
        $summary = is_array($payload['provider_summary'] ?? null) ? $payload['provider_summary'] : null;

        if ($summary === null) {
            return 'Not connected';
        }

        $readiness = is_string($summary['readiness_summary'] ?? null) ? $summary['readiness_summary'] : 'Needs review';
        $targetScope = is_string($summary['target_scope_summary'] ?? null) ? $summary['target_scope_summary'] : null;

        return $targetScope === null || $targetScope === ''
            ? $readiness
            : sprintf('%s - %s', $readiness, $targetScope);
    }

    /**
     * @param  array<string, mixed>  $payload
     */
    private function readinessSummaryColor(array $payload): string
    {
        $summary = strtolower((string) ($payload['blocker']['operator_summary'] ?? ''));

        if (str_contains($summary, 'ready') || str_contains($summary, 'completed')) {
            return 'success';
        }

        if (str_contains($summary, 'running') || str_contains($summary, 'continue')) {
            return 'info';
        }

        if (str_contains($summary, 'required') || str_contains($summary, 'disabled') || str_contains($summary, 'attention') || str_contains($summary, 'refresh')) {
            return 'warning';
        }

        return 'gray';
    }

    private function readinessLifecycleColor(string $state): string
    {
        return match ($state) {
            OnboardingLifecycleState::ReadyForActivation->value,
            OnboardingLifecycleState::Completed->value => 'success',
            OnboardingLifecycleState::Verifying->value,
            OnboardingLifecycleState::Bootstrapping->value => 'info',
            OnboardingLifecycleState::ActionRequired->value => 'warning',
            OnboardingLifecycleState::Cancelled->value => 'danger',
            default => 'gray',
        };
    }

    private function readinessNextActionColor(string $kind): string
    {
        return match ($kind) {
            'complete_onboarding' => 'success',
            'grant_consent',
            'review_provider_connection',
            'review_permissions',
            'rerun_verification',
            'review_bootstrap' => 'warning',
            'start_verification',
            'open_operation' => 'info',
            default => 'gray',
        };
    }

    /**
     * @param  array<string, mixed>  $payload
     */
    private function readinessPrimaryNextActionComponent(array $payload, string $keyPrefix): \Filament\Schemas\Components\Component
    {
        $nextAction = is_array($payload['next_action'] ?? null) ? $payload['next_action'] : [];
        $label = is_string($nextAction['label'] ?? null) && trim((string) $nextAction['label']) !== ''
            ? trim((string) $nextAction['label'])
            : 'Continue onboarding';
        $kind = is_string($nextAction['kind'] ?? null) ? $nextAction['kind'] : 'gray';
        $url = is_string($nextAction['url'] ?? null) && trim((string) $nextAction['url']) !== ''
            ? trim((string) $nextAction['url'])
            : null;

        if ($url !== null) {
            return SchemaActions::make([
                Action::make($keyPrefix.'_primary_next_action')
                    ->label($label)
                    ->color($this->readinessNextActionColor($kind))
                    ->url($url)
                    ->openUrlInNewTab(str_starts_with($url, 'http://') || str_starts_with($url, 'https://')),
            ])->key($keyPrefix.'_primary_next_action');
        }

        return Text::make($label)
            ->badge()
            ->color($this->readinessNextActionColor($kind));
    }

    private function readinessProviderConnection(ManagedEnvironmentOnboardingSession $draft): ?ProviderConnection
    {
        $state = is_array($draft->state) ? $draft->state : [];
        $providerConnectionId = $this->normalizeReadinessInteger(
            $state['provider_connection_id'] ?? $state['selected_provider_connection_id'] ?? null,
        );

        if ($providerConnectionId === null || $draft->managed_environment_id === null) {
            return null;
        }

        return ProviderConnection::query()
            ->whereKey($providerConnectionId)
            ->where('workspace_id', (int) $draft->workspace_id)
            ->where('managed_environment_id', (int) $draft->managed_environment_id)
            ->first();
    }

    /**
     * @return array<string, mixed>|null
     */
    private function readinessProviderSummary(?ProviderConnection $connection): ?array
    {
        if (! $connection instanceof ProviderConnection) {
            return null;
        }

        try {
            $summary = ProviderConnectionSurfaceSummary::forConnection($connection);
        } catch (InvalidArgumentException) {
            return [
                'provider' => (string) $connection->provider,
                'target_scope' => [],
                'consent_state' => $this->stringValue($connection->consent_status),
                'verification_state' => $this->stringValue($connection->verification_status),
                'readiness_summary' => 'Target scope needs review',
                'target_scope_summary' => 'Target scope needs review',
                'provider_context' => [
                    'provider' => (string) $connection->provider,
                    'details' => [],
                ],
                'contextual_identity_line' => null,
                'is_enabled' => (bool) $connection->is_enabled,
            ];
        }

        return $summary->toArray();
    }

    /**
     * @return array{overall: string|null, counts: array<string, int>, freshness: array{last_refreshed_at: string|null, is_stale: bool}, capability_groups: array<int, array<string, mixed>>, primary_capability_group: array<string, mixed>|null, missing_permissions: array{application: list<string>, delegated: list<string>}, required_permissions_url: string|null}
     */
    private function readinessPermissionOverview(ManagedEnvironment $tenant): array
    {
        $viewModel = app(ManagedEnvironmentRequiredPermissionsViewModelBuilder::class)->build($tenant, [
            'status' => 'all',
            'type' => 'all',
            'features' => [],
            'search' => '',
        ]);

        $overview = is_array($viewModel['overview'] ?? null) ? $viewModel['overview'] : [];
        $counts = is_array($overview['counts'] ?? null) ? $overview['counts'] : [];
        $freshness = is_array($overview['freshness'] ?? null) ? $overview['freshness'] : [];
        $capabilityGroups = is_array($overview['capability_groups'] ?? null) ? $overview['capability_groups'] : [];
        $primaryCapabilityGroup = is_array($overview['primary_capability_group'] ?? null)
            ? $overview['primary_capability_group']
            : null;
        $permissions = is_array($viewModel['permissions'] ?? null) ? $viewModel['permissions'] : [];

        return [
            'overall' => is_string($overview['overall'] ?? null) ? $overview['overall'] : null,
            'counts' => [
                'missing_application' => max(0, (int) ($counts['missing_application'] ?? 0)),
                'missing_delegated' => max(0, (int) ($counts['missing_delegated'] ?? 0)),
                'present' => max(0, (int) ($counts['present'] ?? 0)),
                'error' => max(0, (int) ($counts['error'] ?? 0)),
            ],
            'freshness' => [
                'last_refreshed_at' => is_string($freshness['last_refreshed_at'] ?? null) ? $freshness['last_refreshed_at'] : null,
                'is_stale' => (bool) ($freshness['is_stale'] ?? true),
            ],
            'capability_groups' => $capabilityGroups,
            'primary_capability_group' => $primaryCapabilityGroup,
            'missing_permissions' => [
                'application' => $this->readinessMissingPermissionKeys($permissions, 'application'),
                'delegated' => $this->readinessMissingPermissionKeys($permissions, 'delegated'),
            ],
            'required_permissions_url' => RequiredPermissionsLinks::requiredPermissions($tenant),
        ];
    }

    /**
     * @param  array<int, mixed>  $permissions
     * @param  'application'|'delegated'  $type
     * @return list<string>
     */
    private function readinessMissingPermissionKeys(array $permissions, string $type): array
    {
        return collect($permissions)
            ->filter(static fn (mixed $row): bool => is_array($row)
                && ($row['status'] ?? null) === 'missing'
                && ($row['type'] ?? null) === $type
                && is_string($row['key'] ?? null)
                && trim((string) $row['key']) !== '')
            ->map(static fn (array $row): string => trim((string) $row['key']))
            ->values()
            ->all();
    }

    /**
     * @param  array<string, mixed>|null  $permissions
     */
    private function readinessPrimaryCapabilityLabel(?array $permissions): ?string
    {
        $primary = is_array($permissions['primary_capability_group'] ?? null)
            ? $permissions['primary_capability_group']
            : null;

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

        $label = is_string($primary['label'] ?? null) ? trim((string) $primary['label']) : '';

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

    /**
     * @param  array<string, mixed>  $permissions
     */
    private function readinessPrimaryCapabilityLine(array $permissions): string
    {
        $primary = is_array($permissions['primary_capability_group'] ?? null)
            ? $permissions['primary_capability_group']
            : [];
        $label = is_string($primary['label'] ?? null) && trim((string) $primary['label']) !== ''
            ? trim((string) $primary['label'])
            : 'Provider capability';
        $status = is_string($primary['status'] ?? null) ? trim((string) $primary['status']) : 'unknown';
        $statusLabel = BadgeCatalog::spec(BadgeDomain::ProviderCapabilityStatus, $status)->label;

        return "{$label}: {$statusLabel}";
    }

    /**
     * @param  array<string, mixed>  $permissions
     */
    private function readinessPrimaryCapabilityColor(array $permissions): string
    {
        $primary = is_array($permissions['primary_capability_group'] ?? null)
            ? $permissions['primary_capability_group']
            : [];
        $status = is_string($primary['status'] ?? null) ? trim((string) $primary['status']) : 'unknown';

        return BadgeCatalog::spec(BadgeDomain::ProviderCapabilityStatus, $status)->color;
    }

    /**
     * @param  array<string, mixed>  $permissions
     * @param  'application'|'delegated'  $type
     */
    private function readinessMissingPermissionLine(array $permissions, string $type): ?string
    {
        $missing = is_array($permissions['missing_permissions'][$type] ?? null)
            ? $permissions['missing_permissions'][$type]
            : [];

        $missing = array_values(array_filter($missing, static fn (mixed $value): bool => is_string($value) && trim($value) !== ''));

        if ($missing === []) {
            return null;
        }

        return implode(', ', array_slice($missing, 0, 5));
    }

    /**
     * @param  array{last_refreshed_at?: string|null, is_stale?: bool}  $permissionFreshness
     */
    private function readinessFreshnessNote(
        ?OperationRun $verificationRun,
        string $verificationStatus,
        bool $connectionRecentlyUpdated,
        bool $verificationMismatch,
        array $permissionFreshness,
    ): string {
        if (! $verificationRun instanceof OperationRun) {
            return 'Verification has not run yet.';
        }

        if ($connectionRecentlyUpdated) {
            return 'Provider connection changed; rerun verification to refresh readiness.';
        }

        if ($verificationMismatch) {
            return 'Verification evidence belongs to a different provider connection.';
        }

        if ((bool) ($permissionFreshness['is_stale'] ?? true)) {
            return is_string($permissionFreshness['last_refreshed_at'] ?? null)
                ? 'Permission data is older than the 30-day freshness window.'
                : 'Permission check has not run yet.';
        }

        if ($verificationStatus === 'in_progress') {
            return 'Verification is running; refresh for the latest result.';
        }

        return 'Verification and permission evidence are current.';
    }

    /**
     * @param  array<string, mixed>|null  $permissions
     */
    private function readinessSummaryText(
        ManagedEnvironmentOnboardingSession $draft,
        OnboardingLifecycleState $lifecycleState,
        ?ProviderConnection $providerConnection,
        ?OperationRun $verificationRun,
        string $verificationStatus,
        ?array $permissions,
        bool $connectionRecentlyUpdated,
        bool $verificationMismatch,
    ): string {
        if (! $this->readinessDraftHasEnvironmentIdentity($draft)) {
            return 'ManagedEnvironment identity required';
        }

        if (! $providerConnection instanceof ProviderConnection) {
            return 'Provider connection required';
        }

        if (! (bool) $providerConnection->is_enabled) {
            return 'Provider connection disabled';
        }

        $consentState = $providerConnection->consent_status instanceof ProviderConsentStatus
            ? $providerConnection->consent_status->value
            : (string) $providerConnection->consent_status;

        if ($consentState !== ProviderConsentStatus::Granted->value) {
            return match ($consentState) {
                ProviderConsentStatus::Revoked->value => 'Provider consent revoked',
                ProviderConsentStatus::Failed->value => 'Provider consent failed',
                default => 'Provider consent required',
            };
        }

        if ($connectionRecentlyUpdated || $verificationMismatch) {
            return 'Verification needs refresh';
        }

        if (! $verificationRun instanceof OperationRun) {
            return 'Verification has not run yet';
        }

        if ($verificationStatus === 'in_progress') {
            return 'Verification running';
        }

        $permissionOverall = is_string($permissions['overall'] ?? null) ? $permissions['overall'] : null;

        if ($verificationStatus === 'blocked' || $permissionOverall === VerificationReportOverall::Blocked->value) {
            $capabilityLabel = $this->readinessPrimaryCapabilityLabel($permissions);

            return $capabilityLabel !== null
                ? "{$capabilityLabel} capability needs attention"
                : 'Permission or consent blocker needs attention';
        }

        if ($permissionOverall === VerificationReportOverall::NeedsAttention->value || (bool) ($permissions['freshness']['is_stale'] ?? false)) {
            $capabilityLabel = $this->readinessPrimaryCapabilityLabel($permissions);

            return $capabilityLabel !== null
                ? "{$capabilityLabel} capability needs refreshed evidence"
                : 'Readiness needs attention';
        }

        return match ($lifecycleState) {
            OnboardingLifecycleState::Verifying => 'Verification running',
            OnboardingLifecycleState::Bootstrapping => 'Bootstrap running',
            OnboardingLifecycleState::ActionRequired => 'Onboarding needs attention',
            OnboardingLifecycleState::ReadyForActivation => 'Ready for activation',
            OnboardingLifecycleState::Completed => 'Completed',
            OnboardingLifecycleState::Cancelled => 'Cancelled',
            default => 'Continue onboarding',
        };
    }

    /**
     * @param  array<string, mixed>|null  $permissions
     * @param  list<array{label: string, url: string}>  $supportingLinks
     * @return array{label: string, kind: string, url: string|null, action_name: string|null, required_capability: string|null}
     */
    private function readinessNextAction(
        ManagedEnvironmentOnboardingSession $draft,
        OnboardingLifecycleState $lifecycleState,
        ?ProviderConnection $providerConnection,
        ?OperationRun $verificationRun,
        string $verificationStatus,
        ?array $permissions,
        ?string $blockerReasonCode,
        bool $connectionRecentlyUpdated,
        bool $verificationMismatch,
        array $supportingLinks,
    ): array {
        if (! $this->readinessDraftHasEnvironmentIdentity($draft)) {
            return $this->readinessAction('Identify environment', 'start_onboarding');
        }

        if (! $providerConnection instanceof ProviderConnection) {
            return $this->readinessAction('Connect provider', 'resume_draft');
        }

        $consentState = $providerConnection->consent_status instanceof ProviderConsentStatus
            ? $providerConnection->consent_status->value
            : (string) $providerConnection->consent_status;

        if (! (bool) $providerConnection->is_enabled) {
            return $this->readinessAction(
                label: 'Review provider connection',
                kind: 'review_provider_connection',
            );
        }

        if ($consentState !== ProviderConsentStatus::Granted->value) {
            return $this->readinessAction(
                label: 'Grant admin consent',
                kind: 'grant_consent',
                url: $draft->managedEnvironment instanceof ManagedEnvironment ? RequiredPermissionsLinks::adminConsentPrimaryUrl($draft->managedEnvironment) : null,
            );
        }

        $permissionOverall = is_string($permissions['overall'] ?? null) ? $permissions['overall'] : null;

        if (in_array($blockerReasonCode, [
            ProviderReasonCodes::ProviderConsentMissing,
            ProviderReasonCodes::ProviderConsentFailed,
            ProviderReasonCodes::ProviderConsentRevoked,
        ], true)) {
            return $this->readinessAction(
                label: 'Grant admin consent',
                kind: 'grant_consent',
                url: $draft->managedEnvironment instanceof ManagedEnvironment ? RequiredPermissionsLinks::adminConsentPrimaryUrl($draft->managedEnvironment) : null,
            );
        }

        if ($permissionOverall === VerificationReportOverall::Blocked->value) {
            return $this->readinessAction(
                label: 'Review provider capability',
                kind: 'review_permissions',
                url: $draft->managedEnvironment instanceof ManagedEnvironment ? RequiredPermissionsLinks::requiredPermissions($draft->managedEnvironment) : null,
            );
        }

        if (! $verificationRun instanceof OperationRun) {
            return $this->readinessAction(
                label: 'Start verification',
                kind: 'start_verification',
                actionName: 'wizardStartVerification',
                requiredCapability: Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_VERIFICATION_START,
            );
        }

        if ($connectionRecentlyUpdated || $verificationMismatch || (bool) ($permissions['freshness']['is_stale'] ?? false)) {
            return $this->readinessAction(
                label: 'Rerun verification',
                kind: 'rerun_verification',
                actionName: 'wizardStartVerification',
                requiredCapability: Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_VERIFICATION_START,
            );
        }

        if ($verificationStatus === 'in_progress' && $supportingLinks !== []) {
            return $this->readinessAction(
                label: OperationRunLinks::openLabel(),
                kind: 'open_operation',
                url: $supportingLinks[0]['url'],
            );
        }

        if ($lifecycleState === OnboardingLifecycleState::Bootstrapping || $lifecycleState === OnboardingLifecycleState::ActionRequired) {
            return $this->readinessAction('Review bootstrap', 'review_bootstrap');
        }

        if ($lifecycleState === OnboardingLifecycleState::ReadyForActivation) {
            return $this->readinessAction(
                label: 'Complete onboarding',
                kind: 'complete_onboarding',
                actionName: 'wizardCompleteOnboarding',
                requiredCapability: Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_ACTIVATE,
            );
        }

        return $this->readinessAction('Continue onboarding', 'resume_draft');
    }

    /**
     * @return array{label: string, kind: string, url: string|null, action_name: string|null, required_capability: string|null}
     */
    private function readinessAction(
        string $label,
        string $kind,
        ?string $url = null,
        ?string $actionName = null,
        ?string $requiredCapability = null,
    ): array {
        return [
            'label' => $label,
            'kind' => $kind,
            'url' => $url,
            'action_name' => $actionName,
            'required_capability' => $requiredCapability,
        ];
    }

    /**
     * @return list<array{label: string, url: string}>
     */
    private function readinessSupportingLinks(?OperationRun $verificationRun, ManagedEnvironmentOnboardingSession $draft, ?int $selectedProviderConnectionId): array
    {
        $links = [];

        if ($verificationRun instanceof OperationRun && $this->canInspectOperationRun($verificationRun)) {
            $links[] = [
                'label' => OperationRunLinks::openLabel(),
                'url' => OperationRunLinks::tenantlessView($verificationRun),
            ];
        }

        foreach ($this->lifecycleService()->bootstrapRunSummaries($draft, $selectedProviderConnectionId) as $summary) {
            $runId = $this->normalizeReadinessInteger($summary['run_id'] ?? null);

            if ($runId === null) {
                continue;
            }

            $run = OperationRun::query()
                ->whereKey($runId)
                ->where('workspace_id', (int) $draft->workspace_id)
                ->first();

            if (! $run instanceof OperationRun || ! $this->canInspectOperationRun($run)) {
                continue;
            }

            $links[] = [
                'label' => OperationRunLinks::openLabel(),
                'url' => OperationRunLinks::tenantlessView($run),
            ];
        }

        return array_values(array_unique($links, SORT_REGULAR));
    }

    private function readinessVerificationOverall(OperationRun $run, ?array $report = null): ?string
    {
        $report ??= VerificationReportViewer::report($run);
        $summary = is_array($report['summary'] ?? null) ? $report['summary'] : [];
        $overall = $summary['overall'] ?? null;

        return is_string($overall) && in_array($overall, VerificationReportOverall::values(), true)
            ? $overall
            : null;
    }

    private function readinessRunMatchesSelectedConnection(OperationRun $run, ?int $selectedProviderConnectionId): bool
    {
        if ($selectedProviderConnectionId === null) {
            return false;
        }

        $context = is_array($run->context ?? null) ? $run->context : [];
        $runProviderConnectionId = $this->normalizeReadinessInteger($context['provider_connection_id'] ?? null);

        return $runProviderConnectionId !== null && $runProviderConnectionId === $selectedProviderConnectionId;
    }

    private function readinessConnectionRecentlyUpdated(ManagedEnvironmentOnboardingSession $draft): bool
    {
        $state = is_array($draft->state) ? $draft->state : [];

        return (bool) ($state['connection_recently_updated'] ?? false);
    }

    private function readinessDraftHasEnvironmentIdentity(ManagedEnvironmentOnboardingSession $draft): bool
    {
        if ($draft->managed_environment_id !== null) {
            return true;
        }

        $state = is_array($draft->state) ? $draft->state : [];
        $entraTenantId = $state['entra_tenant_id'] ?? $draft->entra_tenant_id;

        return is_string($entraTenantId) && trim($entraTenantId) !== '';
    }

    private function normalizeReadinessInteger(mixed $value): ?int
    {
        if (is_int($value) && $value > 0) {
            return $value;
        }

        if (is_string($value) && ctype_digit(trim($value))) {
            return (int) trim($value);
        }

        if (is_numeric($value)) {
            $normalized = (int) $value;

            return $normalized > 0 ? $normalized : null;
        }

        return null;
    }

    /**
     * @return array<int, \Filament\Schemas\Components\Component>
     */
    private function nonResumableSummarySchema(): array
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return [];
        }

        $statusLabel = $draft->status()->label();

        return [
            Callout::make("This onboarding draft is {$statusLabel}.")
                ->description('Completed, cancelled, and lifecycle-locked drafts remain viewable, but they cannot return to editable wizard mode.')
                ->warning(),
            ...$this->resumeContextSchema(),
            Section::make('Draft summary')
                ->compact()
                ->columns(2)
                ->schema([
                    Text::make('Status')
                        ->color('gray'),
                    Text::make(fn (): string => $statusLabel)
                        ->badge()
                        ->color(fn () => $this->draftStatusColor($this->currentOnboardingSessionRecord() ?? $draft)),
                    Text::make('Primary domain')
                        ->color('gray'),
                    Text::make(fn () => (string) ((($this->currentOnboardingSessionRecord() ?? $draft)?->state['primary_domain'] ?? null) ?: '—')),
                    Text::make('Environment')
                        ->color('gray'),
                    Text::make(fn () => (string) ((($this->currentOnboardingSessionRecord() ?? $draft)?->state['environment'] ?? null) ?: '—')),
                    Text::make('Notes')
                        ->color('gray'),
                    Text::make(fn () => (string) ((($this->currentOnboardingSessionRecord() ?? $draft)?->state['notes'] ?? null) ?: '—')),
                ]),
            SchemaActions::make([
                Action::make('back_to_workspace_summary')
                    ->label('Back to workspace')
                    ->color('gray')
                    ->url(route('admin.home')),
                Action::make('return_to_onboarding_landing')
                    ->label('Return to onboarding')
                    ->color('gray')
                    ->url(route('admin.onboarding')),
                Action::make('delete_onboarding_draft')
                    ->label('Delete draft')
                    ->color('danger')
                    ->requiresConfirmation()
                    ->modalHeading('Delete onboarding draft')
                    ->modalDescription('This permanently deletes the onboarding draft record. The linked environment record, if any, is not deleted.')
                    ->modalSubmitActionLabel('Delete draft')
                    ->visible(fn (): bool => $this->canDeleteDraft($this->currentOnboardingSessionRecord() ?? $draft))
                    ->action(fn () => $this->deleteOnboardingDraft()),
            ]),
        ];
    }

    private function startNewOnboardingDraft(): void
    {
        $this->showDraftPicker = false;
        $this->showStartState = true;
        $this->setManagedEnvironment(null);
        $this->setOnboardingSession(null);
        $this->selectedProviderConnectionId = null;
        $this->selectedBootstrapOperationTypes = [];
        $this->data = [];

        $this->initializeWizardData();
    }

    private function resumeOnboardingDraft(int $draftId, bool $logSelection): void
    {
        $user = $this->currentUser();

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

        $draft = app(OnboardingDraftResolver::class)->resolve($draftId, $user, $this->workspace);

        if ($logSelection) {
            app(WorkspaceAuditLogger::class)->log(
                workspace: $this->workspace,
                action: AuditActionId::ManagedEnvironmentOnboardingDraftSelected->value,
                context: [
                    'metadata' => [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'onboarding_session_id' => (int) $draft->getKey(),
                        'tenant_db_id' => $draft->managed_environment_id !== null ? (int) $draft->managed_environment_id : null,
                    ],
                ],
                actor: $user,
                status: 'success',
                resourceType: 'managed_environment_onboarding_session',
                resourceId: (string) $draft->getKey(),
            );
        }

        $this->redirect(route('admin.onboarding.draft', ['onboardingDraft' => $draft]));
    }

    private function cancelOnboardingDraft(): void
    {
        $user = $this->currentUser();

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

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            abort(404);
        }

        $this->authorizeWorkspaceMember($user);

        $draft = app(TrustedStateResolver::class)->resolveOnboardingDraft(
            $this->onboardingSessionId ?? $this->onboardingSession,
            $user,
            $this->workspace,
            app(OnboardingDraftResolver::class),
        );

        $this->setOnboardingSession($draft);

        $this->authorize('cancel', $draft);

        if (! $this->canResumeDraft($draft)) {
            Notification::make()
                ->title('Draft is not resumable')
                ->warning()
                ->send();

            return;
        }

        try {
            $this->setOnboardingSession($this->mutationService()->mutate(
                draft: $this->onboardingSession,
                actor: $user,
                expectedVersion: $this->expectedDraftVersion(),
                mutator: function (ManagedEnvironmentOnboardingSession $draft): void {
                    $draft->current_step = 'cancelled';
                    $draft->completed_at = null;
                    $draft->cancelled_at = now();
                },
            ));
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict();

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft();

            return;
        }

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingCancelled->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => $this->onboardingSession->managed_environment_id !== null ? (int) $this->onboardingSession->managed_environment_id : null,
                    'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                ],
            ],
            actor: $user,
            status: 'success',
            resourceType: 'managed_environment_onboarding_session',
            resourceId: (string) $this->onboardingSession->getKey(),
        );

        $normalizedTenant = $this->lifecycleService()->syncLinkedTenantAfterCancellation($this->onboardingSession);

        if ($normalizedTenant instanceof ManagedEnvironment) {
            app(WorkspaceAuditLogger::class)->logTenantLifecycleAction(
                tenant: $normalizedTenant,
                action: AuditActionId::TenantReturnedToDraft,
                actor: $user,
                context: [
                    'metadata' => [
                        'source' => 'onboarding_cancel',
                        'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                    ],
                ],
            );

            $this->setManagedEnvironment($normalizedTenant);
        }

        Notification::make()
            ->title('Onboarding draft cancelled')
            ->success()
            ->send();

        $this->redirect(route('admin.onboarding.draft', ['onboardingDraft' => $this->onboardingSession]));
    }

    private function deleteOnboardingDraft(): void
    {
        $user = $this->currentUser();

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

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            abort(404);
        }

        $this->authorizeWorkspaceMember($user);

        $draft = app(TrustedStateResolver::class)->resolveOnboardingDraft(
            $this->onboardingSessionId ?? $this->onboardingSession,
            $user,
            $this->workspace,
            app(OnboardingDraftResolver::class),
        );

        $this->setOnboardingSession($draft);

        $this->authorize('cancel', $draft);

        if (! $this->canDeleteDraft($draft)) {
            Notification::make()
                ->title('Draft cannot be deleted')
                ->warning()
                ->send();

            return;
        }

        $draftId = (int) $draft->getKey();
        $draftTitle = $this->draftTitle($draft);
        $draftStatus = $draft->status()->value;
        $draftLifecycle = $draft->lifecycleState()->value;
        $tenantId = $draft->managed_environment_id !== null ? (int) $draft->managed_environment_id : null;

        $draft->delete();

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingDeleted->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'onboarding_session_id' => $draftId,
                    'tenant_db_id' => $tenantId,
                    'status' => $draftStatus,
                    'lifecycle_state' => $draftLifecycle,
                ],
            ],
            actor: $user,
            status: 'success',
            resourceType: 'managed_environment_onboarding_session',
            resourceId: (string) $draftId,
            targetLabel: $draftTitle,
        );

        $this->setManagedEnvironment(null);
        $this->setOnboardingSession(null);

        Notification::make()
            ->title('Onboarding draft deleted')
            ->success()
            ->send();

        $this->redirect(route('admin.onboarding'));
    }

    private function showsNonResumableSummary(): bool
    {
        $draft = $this->currentOnboardingSessionRecord();

        return $draft instanceof ManagedEnvironmentOnboardingSession
            && ! $this->canResumeDraft($draft);
    }

    private function canDeleteDraft(?ManagedEnvironmentOnboardingSession $draft): bool
    {
        return $draft instanceof ManagedEnvironmentOnboardingSession
            && ! $this->canResumeDraft($draft)
            && $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CANCEL);
    }

    private function onboardingDraftLandingActionLabel(): string
    {
        $user = $this->currentUser();

        if (! $user instanceof User) {
            return 'Choose onboarding draft';
        }

        return $this->onboardingEntryActionDescriptor($this->availableDraftsFor($user)->count())->label;
    }

    private function resumeOnboardingActionLabel(): string
    {
        return $this->onboardingEntryActionDescriptor(1)->label;
    }

    private function onboardingEntryActionDescriptor(int $resumableDraftCount): \App\Support\Tenants\TenantActionDescriptor
    {
        return ManagedEnvironmentResource::tenantActionPolicy()->onboardingEntryDescriptor($resumableDraftCount);
    }

    private function shouldShowDraftLandingAction(): bool
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return false;
        }

        if (! $this->canResumeDraft($draft)) {
            return false;
        }

        if (! isset($this->workspace)) {
            return false;
        }

        $user = $this->currentUser();

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

        return $this->availableDraftsFor($user)->count() > 1;
    }

    private function draftTitle(ManagedEnvironmentOnboardingSession $draft): string
    {
        $state = is_array($draft->state) ? $draft->state : [];
        $environmentName = $state['environment_name'] ?? $draft->managedEnvironment?->name ?? null;
        $environmentName = is_string($environmentName) && trim($environmentName) !== '' ? trim($environmentName) : 'Unidentified environment';
        $entraTenantId = $state['entra_tenant_id'] ?? $draft->entra_tenant_id;

        if (is_string($entraTenantId) && trim($entraTenantId) !== '') {
            return sprintf('%s (%s)', $environmentName, trim($entraTenantId));
        }

        return $environmentName;
    }

    private function draftDescription(ManagedEnvironmentOnboardingSession $draft): string
    {
        $state = is_array($draft->state) ? $draft->state : [];
        $environment = $state['environment'] ?? null;
        $primaryDomain = $state['primary_domain'] ?? null;

        return collect([
            is_string($environment) && $environment !== '' ? ucfirst($environment) : null,
            is_string($primaryDomain) && $primaryDomain !== '' ? $primaryDomain : null,
        ])->filter()->implode(' · ');
    }

    private function draftStageLabel(ManagedEnvironmentOnboardingSession $draft): string
    {
        return app(OnboardingDraftStageResolver::class)->resolve($draft)->label();
    }

    private function draftStageColor(ManagedEnvironmentOnboardingSession $draft): string
    {
        return match (app(OnboardingDraftStageResolver::class)->resolve($draft)) {
            OnboardingDraftStage::Identify => 'gray',
            OnboardingDraftStage::ConnectProvider => 'info',
            OnboardingDraftStage::VerifyAccess => 'warning',
            OnboardingDraftStage::Bootstrap => 'info',
            OnboardingDraftStage::Review => 'success',
            OnboardingDraftStage::Completed => 'success',
            OnboardingDraftStage::Cancelled => 'danger',
        };
    }

    private function draftStatusColor(ManagedEnvironmentOnboardingSession $draft): string
    {
        return match ($draft->status()->value) {
            'draft' => 'info',
            'completed' => 'success',
            'cancelled' => 'danger',
            default => 'gray',
        };
    }

    private function currentUser(): ?User
    {
        $user = auth()->user();

        return $user instanceof User ? $user : null;
    }

    private function lifecycleService(): OnboardingLifecycleService
    {
        return app(OnboardingLifecycleService::class);
    }

    private function mutationService(): OnboardingDraftMutationService
    {
        return app(OnboardingDraftMutationService::class);
    }

    private function expectedDraftVersion(): ?int
    {
        return is_int($this->onboardingSessionVersion) && $this->onboardingSessionVersion > 0
            ? $this->onboardingSessionVersion
            : null;
    }

    private function setOnboardingSession(?ManagedEnvironmentOnboardingSession $draft): void
    {
        $this->onboardingSession = $draft;
        $this->onboardingSessionId = $draft instanceof ManagedEnvironmentOnboardingSession
            ? (int) $draft->getKey()
            : null;
        $this->onboardingSessionVersion = $draft instanceof ManagedEnvironmentOnboardingSession
            ? $draft->expectedVersion()
            : null;

        if ($draft instanceof ManagedEnvironmentOnboardingSession && $draft->managedEnvironment instanceof ManagedEnvironment) {
            $this->setManagedEnvironment($draft->managedEnvironment);

            return;
        }

        if ($draft instanceof ManagedEnvironmentOnboardingSession && $draft->managed_environment_id !== null) {
            $this->managedEnvironmentId = (int) $draft->managed_environment_id;

            return;
        }

        $this->setManagedEnvironment(null);
    }

    private function setManagedEnvironment(?ManagedEnvironment $tenant): void
    {
        $this->managedEnvironment = $tenant;
        $this->managedEnvironmentId = $tenant instanceof ManagedEnvironment
            ? (int) $tenant->getKey()
            : null;

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession && $tenant instanceof ManagedEnvironment) {
            $this->onboardingSession->setRelation('managedEnvironment', $tenant);
        }
    }

    private function currentOnboardingSessionRecord(): ?ManagedEnvironmentOnboardingSession
    {
        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession
            && $this->onboardingSessionId !== null
            && (int) $this->onboardingSession->getKey() === $this->onboardingSessionId) {
            return $this->onboardingSession;
        }

        if ($this->onboardingSessionId === null) {
            return $this->onboardingSession;
        }

        $query = ManagedEnvironmentOnboardingSession::query()
            ->with(['managedEnvironment', 'startedByUser', 'updatedByUser'])
            ->whereKey($this->onboardingSessionId);

        if (isset($this->workspace)) {
            $query->where('workspace_id', (int) $this->workspace->getKey());
        }

        return $query->first();
    }

    private function currentManagedEnvironmentRecord(): ?ManagedEnvironment
    {
        $draft = $this->currentOnboardingSessionRecord();

        if ($draft instanceof ManagedEnvironmentOnboardingSession && $draft->managedEnvironment instanceof ManagedEnvironment) {
            return $draft->managedEnvironment;
        }

        if ($this->managedEnvironment instanceof ManagedEnvironment
            && $this->managedEnvironmentId !== null
            && (int) $this->managedEnvironment->getKey() === $this->managedEnvironmentId) {
            return $this->managedEnvironment;
        }

        if ($this->managedEnvironmentId === null) {
            return $this->managedEnvironment;
        }

        $query = ManagedEnvironment::query()->withTrashed()->whereKey($this->managedEnvironmentId);

        if (isset($this->workspace)) {
            $query->where('workspace_id', (int) $this->workspace->getKey());
        }

        return $query->first();
    }

    private function refreshOnboardingDraftFromBackend(): void
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return;
        }

        $user = $this->currentUser();

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

        $this->setOnboardingSession(app(OnboardingDraftResolver::class)->resolve(
            $draft,
            $user,
            $this->workspace,
        ));

        $providerConnectionId = $this->onboardingSession->state['provider_connection_id'] ?? null;
        $this->selectedProviderConnectionId = $this->resolvePersistedProviderConnectionId($providerConnectionId);
        $this->initializeWizardData();
    }

    private function handleDraftConflict(string $title = 'This onboarding draft changed in another tab or session.'): void
    {
        $this->refreshOnboardingDraftFromBackend();

        Notification::make()
            ->title($title)
            ->body('TenantAtlas refreshed the latest saved state. Review it and try again.')
            ->warning()
            ->send();
    }

    private function handleImmutableDraft(string $title = 'This onboarding draft is no longer editable.'): void
    {
        $this->refreshOnboardingDraftFromBackend();

        Notification::make()
            ->title($title)
            ->body('The latest draft state is now shown below.')
            ->warning()
            ->send();
    }

    private function lifecycleState(): OnboardingLifecycleState
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return OnboardingLifecycleState::Draft;
        }

        return $this->lifecycleService()->snapshot($draft)['lifecycle_state'];
    }

    private function lifecycleStateLabel(): string
    {
        return $this->lifecycleState()->label();
    }

    private function lifecycleStateColor(): string
    {
        return match ($this->lifecycleState()) {
            OnboardingLifecycleState::Draft => 'gray',
            OnboardingLifecycleState::Verifying => 'info',
            OnboardingLifecycleState::ActionRequired => 'warning',
            OnboardingLifecycleState::Bootstrapping => 'info',
            OnboardingLifecycleState::ReadyForActivation => 'success',
            OnboardingLifecycleState::Completed => 'success',
            OnboardingLifecycleState::Cancelled => 'danger',
        };
    }

    private function currentCheckpointLabel(): string
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return OnboardingCheckpoint::Identify->label();
        }

        return ($this->lifecycleService()->snapshot($draft)['current_checkpoint'] ?? OnboardingCheckpoint::Identify)?->label()
            ?? OnboardingCheckpoint::Identify->label();
    }

    public function shouldPollCheckpointLifecycle(): bool
    {
        $draft = $this->currentOnboardingSessionRecord();

        return $draft instanceof ManagedEnvironmentOnboardingSession
            && $this->lifecycleService()->hasActiveCheckpoint($draft);
    }

    public function refreshCheckpointLifecycle(): void
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return;
        }

        $this->setOnboardingSession($this->lifecycleService()->syncPersistedLifecycle($draft));

        $tenant = $this->currentManagedEnvironmentRecord();

        if ($tenant instanceof ManagedEnvironment) {
            $this->setManagedEnvironment($tenant->fresh());
        }

        $this->initializeWizardData();
    }

    private function initializeWizardData(): void
    {
        // Ensure all entangled schema state paths exist at render time.
        // Livewire v4 can throw when entangling to missing nested array keys.
        $this->data['notes'] ??= '';
        $this->data['bootstrap_operation_types'] ??= [];
        $this->data['override_blocked'] ??= false;
        $this->data['override_reason'] ??= '';
        $this->data['new_connection'] ??= [];

        if (! array_key_exists('connection_mode', $this->data)) {
            $this->data['connection_mode'] = 'existing';
        }

        if (is_array($this->data['new_connection'])) {
            $this->data['new_connection']['connection_type'] ??= 'Platform connection';
            $this->data['new_connection']['platform_app_id'] ??= $this->platformAppClientId();
            $this->data['new_connection']['uses_dedicated_override'] ??= false;
            $this->data['new_connection']['is_default'] ??= true;
        }

        $tenant = $this->currentManagedEnvironmentRecord();

        if ($tenant instanceof ManagedEnvironment) {
            $this->data['entra_tenant_id'] ??= (string) $tenant->managed_environment_id;
            $this->data['new_connection']['target_scope_id'] ??= (string) $tenant->managed_environment_id;
            $this->data['environment'] ??= (string) ($tenant->environment ?? 'other');
            $this->data['name'] ??= (string) $tenant->name;
            $this->data['primary_domain'] ??= (string) ($tenant->domain ?? '');

            $notes = is_array($tenant->metadata) ? ($tenant->metadata['notes'] ?? null) : null;
            if (is_string($notes) && trim($notes) !== '') {
                $this->data['notes'] ??= trim($notes);
            }
        }

        $draft = $this->currentOnboardingSessionRecord();

        if ($draft instanceof ManagedEnvironmentOnboardingSession) {
            $state = is_array($draft->state) ? $draft->state : [];

            if (isset($state['entra_tenant_id']) && is_string($state['entra_tenant_id']) && trim($state['entra_tenant_id']) !== '') {
                $this->data['entra_tenant_id'] ??= trim($state['entra_tenant_id']);
            }

            if (isset($state['environment']) && is_string($state['environment']) && trim($state['environment']) !== '') {
                $this->data['environment'] ??= trim($state['environment']);
            }

            if (isset($state['environment_name']) && is_string($state['environment_name']) && trim($state['environment_name']) !== '') {
                $this->data['name'] ??= trim($state['environment_name']);
            }

            if (array_key_exists('primary_domain', $state)) {
                $domain = $state['primary_domain'];

                if (is_string($domain)) {
                    $this->data['primary_domain'] ??= $domain;
                }
            }

            if (array_key_exists('notes', $state)) {
                $notes = $state['notes'];

                if (is_string($notes)) {
                    $this->data['notes'] ??= $notes;
                }
            }

            $providerConnectionId = $this->resolvePersistedProviderConnectionId($draft->state['provider_connection_id'] ?? null);
            if ($providerConnectionId !== null) {
                $this->data['provider_connection_id'] = $providerConnectionId;
                $this->selectedProviderConnectionId = $providerConnectionId;
            }

            $types = $draft->state['bootstrap_operation_types'] ?? null;
            if (is_array($types)) {
                $this->data['bootstrap_operation_types'] = $this->normalizeBootstrapOperationTypes($types);
            }
        }

        $this->selectedProviderConnectionId = $this->resolvePersistedProviderConnectionId($this->selectedProviderConnectionId);

        if ($this->selectedProviderConnectionId !== null) {
            $this->data['provider_connection_id'] = $this->selectedProviderConnectionId;
        } else {
            $this->data['provider_connection_id'] = null;
        }
    }

    private function computeWizardStartStep(): int
    {
        return app(OnboardingDraftStageResolver::class)
            ->resolve($this->currentOnboardingSessionRecord())
            ->wizardStep();
    }

    /**
     * @return array<int, string>
     */
    private function providerConnectionOptions(): array
    {
        $tenant = $this->currentManagedEnvironmentRecord();

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

        return ProviderConnection::query()
            ->with('tenant')
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', $tenant->getKey())
            ->orderByDesc('is_default')
            ->orderBy('display_name')
            ->get()
            ->mapWithKeys(fn (ProviderConnection $connection): array => [
                (int) $connection->getKey() => sprintf(
                    '%s — %s',
                    (string) $connection->display_name,
                    $this->providerConnectionTargetScopeSummary($connection),
                ),
            ])
            ->all();
    }

    private function providerConnectionTargetScopeSummary(ProviderConnection $connection): string
    {
        try {
            return ProviderConnectionSurfaceSummary::forConnection($connection)->targetScopeSummary();
        } catch (InvalidArgumentException) {
            return 'Target scope needs review';
        }
    }

    /**
     * @param  array<string, mixed>  $extra
     * @return array<string, mixed>
     */
    private function providerConnectionTargetScopeAuditMetadata(ProviderConnection $connection, array $extra = []): array
    {
        try {
            return app(ProviderConnectionTargetScopeNormalizer::class)->auditMetadataForConnection($connection, $extra);
        } catch (InvalidArgumentException) {
            return array_merge([
                'provider_connection_id' => (int) $connection->getKey(),
                'provider' => (string) $connection->provider,
                'target_scope' => [
                    'provider' => (string) $connection->provider,
                    'scope_kind' => ProviderConnectionTargetScopeDescriptor::SCOPE_KIND_TENANT,
                    'scope_identifier' => (string) $connection->entra_tenant_id,
                    'scope_display_name' => (string) ($connection->tenant?->name ?? $connection->display_name ?? $connection->entra_tenant_id),
                    'shared_label' => 'Target scope',
                    'shared_help_text' => 'The platform scope this provider connection represents.',
                ],
                'provider_context' => [
                    'provider' => (string) $connection->provider,
                    'details' => [],
                ],
            ], $extra);
        }
    }

    private function verificationStatusLabel(): string
    {
        return BadgeCatalog::spec(
            BadgeDomain::ManagedEnvironmentOnboardingVerificationStatus,
            $this->verificationStatus(),
        )->label;
    }

    private function verificationStatus(): string
    {
        $draft = $this->currentOnboardingSessionRecord();

        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return 'not_started';
        }

        return $this->lifecycleService()->verificationStatus($draft, $this->selectedProviderConnectionId);
    }

    private function verificationStatusFromRunOutcome(OperationRun $run): string
    {
        if ($run->outcome === OperationRunOutcome::Blocked->value) {
            return 'blocked';
        }

        if ($run->outcome === OperationRunOutcome::Succeeded->value) {
            return 'ready';
        }

        if ($run->outcome === OperationRunOutcome::PartiallySucceeded->value) {
            return 'needs_attention';
        }

        if ($run->outcome !== OperationRunOutcome::Failed->value) {
            return 'needs_attention';
        }

        $failures = is_array($run->failure_summary ?? null) ? $run->failure_summary : [];

        if ($failures === []) {
            return 'blocked';
        }

        foreach ($failures as $failure) {
            if (! is_array($failure)) {
                continue;
            }

            $reasonCode = $failure['reason_code'] ?? null;

            if (! is_string($reasonCode) || $reasonCode === '') {
                continue;
            }

            if (in_array($reasonCode, ['provider_auth_failed', 'provider_permission_denied', 'permission_denied', 'provider_consent_missing'], true)) {
                return 'blocked';
            }
        }

        return 'needs_attention';
    }

    private function verificationReportOverall(): ?string
    {
        $run = $this->verificationRun();

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

        $report = VerificationReportViewer::report($run);
        $summary = is_array($report['summary'] ?? null) ? $report['summary'] : null;
        $overall = $summary['overall'] ?? null;

        if (! is_string($overall) || ! in_array($overall, VerificationReportOverall::values(), true)) {
            return null;
        }

        return $overall;
    }

    /**
     * @return array{total: int, pass: int, fail: int, warn: int, skip: int, running: int}|null
     */
    private function verificationReportCounts(): ?array
    {
        $run = $this->verificationRun();

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

        $report = VerificationReportViewer::report($run);
        $summary = is_array($report['summary'] ?? null) ? $report['summary'] : null;
        $counts = is_array($summary['counts'] ?? null) ? $summary['counts'] : null;

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

        foreach (['total', 'pass', 'fail', 'warn', 'skip', 'running'] as $key) {
            if (! is_int($counts[$key] ?? null) || $counts[$key] < 0) {
                return null;
            }
        }

        return [
            'total' => $counts['total'],
            'pass' => $counts['pass'],
            'fail' => $counts['fail'],
            'warn' => $counts['warn'],
            'skip' => $counts['skip'],
            'running' => $counts['running'],
        ];
    }

    private function verificationRunIsActive(): bool
    {
        $run = $this->verificationRun();

        return $run instanceof OperationRun
            && $run->status !== OperationRunStatus::Completed->value;
    }

    private function verificationStatusColor(): string
    {
        return BadgeCatalog::spec(
            BadgeDomain::ManagedEnvironmentOnboardingVerificationStatus,
            $this->verificationStatus(),
        )->color;
    }

    private function verificationRunUrl(): ?string
    {
        $run = $this->verificationRun();

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

        if (! $this->canInspectOperationRun($run)) {
            return null;
        }

        return $this->tenantlessOperationRunUrl((int) $run->getKey());
    }

    /**
     * @return array{
     *   run: array<string, mixed>|null,
     *   runUrl: string|null,
     *   advancedRunUrl: string|null,
     *   report: array<string, mixed>|null,
     *   fingerprint: string|null,
     *   changeIndicator: array{state: 'no_changes'|'changed', previous_report_id: int}|null,
     *   previousRunUrl: string|null,
     *   canAcknowledge: bool,
     *   acknowledgements: array<string, array{
     *     check_key: string,
     *     ack_reason: string,
     *     acknowledged_at: string|null,
     *     expires_at: string|null,
     *     acknowledged_by: array{id: int, name: string}|null
     *   }>,
     *   assistVisibility: array{is_visible: bool, reason: 'permission_blocked'|'permission_attention'|'hidden_ready'|'hidden_irrelevant'},
     *   assistActionName: string,
     *   technicalDetailsActionName: string,
     *   runState: 'no_run'|'active'|'completed'
     * }
     */
    private function verificationReportViewData(): array
    {
        $run = $this->verificationRun();
        $runUrl = $this->verificationRunUrl();
        $assistVisibility = $this->verificationAssistVisibility();

        if (! $run instanceof OperationRun) {
            return [
                'run' => null,
                'runUrl' => $runUrl,
                'advancedRunUrl' => null,
                'report' => null,
                'fingerprint' => null,
                'changeIndicator' => null,
                'previousRunUrl' => null,
                'canAcknowledge' => false,
                'acknowledgements' => [],
                'surface' => [],
                'redactionNotes' => [],
                'contextualHelp' => null,
                'assistVisibility' => $assistVisibility,
                'assistActionName' => 'wizardVerificationRequiredPermissionsAssist',
                'technicalDetailsActionName' => 'wizardVerificationTechnicalDetails',
                'runState' => 'no_run',
            ];
        }

        $report = VerificationReportViewer::report($run);
        $fingerprint = is_array($report) ? VerificationReportViewer::fingerprint($report) : null;
        $contextualHelp = is_array($report) ? $this->verificationContextualHelp($report, $run) : null;

        $changeIndicator = VerificationReportChangeIndicator::forRun($run);
        $previousRunUrl = $this->verificationPreviousRunUrl($changeIndicator);

        $user = auth()->user();
        $canAcknowledge = $user instanceof User && $this->managedEnvironment instanceof ManagedEnvironment
            ? $user->can(Capabilities::TENANT_VERIFICATION_ACKNOWLEDGE, $this->managedEnvironment)
            : false;

        $acknowledgements = VerificationCheckAcknowledgement::query()
            ->where('managed_environment_id', (int) $run->managed_environment_id)
            ->where('workspace_id', (int) $run->workspace_id)
            ->where('operation_run_id', (int) $run->getKey())
            ->with('acknowledgedByUser')
            ->get()
            ->mapWithKeys(static function (VerificationCheckAcknowledgement $ack): array {
                $user = $ack->acknowledgedByUser;

                return [
                    (string) $ack->check_key => [
                        'check_key' => (string) $ack->check_key,
                        'ack_reason' => (string) $ack->ack_reason,
                        'acknowledged_at' => $ack->acknowledged_at?->toJSON(),
                        'expires_at' => $ack->expires_at?->toJSON(),
                        'acknowledged_by' => $user instanceof User
                            ? [
                                'id' => (int) $user->getKey(),
                                'name' => (string) $user->name,
                            ]
                            : null,
                    ],
                ];
            })
            ->all();

        $context = is_array($run->context ?? null) ? $run->context : [];
        $targetScope = $context['target_scope'] ?? [];
        $targetScope = is_array($targetScope) ? $targetScope : [];

        $failures = is_array($run->failure_summary ?? null) ? $run->failure_summary : [];
        $surface = VerificationReportViewer::surface($run, $acknowledgements, [
            'hostKind' => 'onboarding_wizard',
            'changeIndicator' => $changeIndicator,
            'previousRunUrl' => $previousRunUrl,
            'nextStepPlacement' => ($assistVisibility['is_visible'] ?? false) ? 'host_action_zone' : 'shared_zone',
            'hostActions' => array_values(array_filter([
                ($assistVisibility['is_visible'] ?? false)
                    ? ['kind' => 'assist', 'label' => 'View required permissions', 'ownedByHost' => true]
                    : null,
                ['kind' => 'technical_details', 'label' => 'Technical details', 'ownedByHost' => true],
                $canAcknowledge
                    ? ['kind' => 'acknowledge', 'label' => 'Acknowledge', 'ownedByHost' => true]
                    : null,
            ])),
            'hostVariation' => [
                'ownsNoRunState' => true,
                'ownsActiveState' => true,
                'supportsAssist' => (bool) ($assistVisibility['is_visible'] ?? false),
                'supportsAcknowledge' => $canAcknowledge,
                'supportsTechnicalDetailsTrigger' => true,
            ],
        ]);

        return [
            'run' => [
                'id' => (int) $run->getKey(),
                'type' => (string) $run->type,
                'status' => (string) $run->status,
                'outcome' => (string) $run->outcome,
                'initiator_name' => (string) $run->initiator_name,
                'started_at' => $run->started_at?->toJSON(),
                'updated_at' => $run->updated_at?->toJSON(),
                'completed_at' => $run->completed_at?->toJSON(),
                'target_scope' => $targetScope,
                'failures' => $failures,
            ],
            'runUrl' => $runUrl,
            'advancedRunUrl' => $runUrl,
            'report' => $report,
            'fingerprint' => $fingerprint,
            'changeIndicator' => $changeIndicator,
            'previousRunUrl' => $previousRunUrl,
            'canAcknowledge' => $canAcknowledge,
            'acknowledgements' => $acknowledgements,
            'surface' => $surface,
            'redactionNotes' => VerificationReportViewer::redactionNotes($report),
            'contextualHelp' => $contextualHelp,
            'assistVisibility' => $assistVisibility,
            'assistActionName' => 'wizardVerificationRequiredPermissionsAssist',
            'technicalDetailsActionName' => 'wizardVerificationTechnicalDetails',
            'runState' => (string) $run->status === OperationRunStatus::Completed->value ? 'completed' : 'active',
        ];
    }

    /**
     * @param  array<string, mixed>  $verificationReport
     * @return array<string, mixed>|null
     */
    private function verificationContextualHelp(array $verificationReport, OperationRun $run): ?array
    {
        $tenant = $this->managedEnvironment;

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

        $resolver = app(ContextualHelpResolver::class);
        $reasonCode = $resolver->primaryReasonCodeFromVerificationReport($verificationReport);
        $topicKey = $resolver->topicKeyForOnboardingVerification(
            reasonCode: $reasonCode,
            isVerificationStale: $this->verificationRunIsStaleForSelectedConnection(),
            verificationOverall: is_string(data_get($verificationReport, 'summary.overall'))
                ? (string) data_get($verificationReport, 'summary.overall')
                : null,
            runOutcome: is_string($run->outcome) ? (string) $run->outcome : null,
        );

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

        return $resolver->tryResolve($topicKey, [
            'tenant' => $tenant,
            'reason_code' => $reasonCode,
            'surface' => 'onboarding',
        ]);
    }

    public function wizardVerificationRequiredPermissionsAssistAction(): Action
    {
        return Action::make('wizardVerificationRequiredPermissionsAssist')
            ->label('View required permissions')
            ->icon('heroicon-m-key')
            ->color('warning')
            ->modal()
            ->slideOver()
            ->stickyModalHeader()
            ->modalHeading('Required permissions assist')
            ->modalDescription('Review stored permission diagnostics without leaving the onboarding wizard.')
            ->modalSubmitAction(false)
            ->modalCancelAction(fn (Action $action): Action => $action->label('Close'))
            ->modalContent(fn (): View => view('filament.actions.verification-required-permissions-assist', [
                'assist' => $this->verificationAssistViewModel(),
            ]))
            ->visible(fn (): bool => $this->verificationAssistVisibility()['is_visible']);
    }

    public function wizardVerificationTechnicalDetailsAction(): Action
    {
        return Action::make('wizardVerificationTechnicalDetails')
            ->label('Technical details')
            ->icon('heroicon-m-information-circle')
            ->color('gray')
            ->modal()
            ->slideOver()
            ->stickyModalHeader()
            ->modalHeading('Verification technical details')
            ->modalDescription('Diagnostics-only details for the current verification run.')
            ->modalSubmitAction(false)
            ->modalCancelAction(fn (Action $action): Action => $action->label('Close'))
            ->modalContent(fn (): View => view(
                'filament.modals.onboarding-verification-technical-details',
                $this->verificationTechnicalDetailsViewData(),
            ))
            ->visible(fn (): bool => $this->verificationRun() instanceof OperationRun);
    }

    public function acknowledgeVerificationCheckAction(): Action
    {
        return Action::make('acknowledgeVerificationCheck')
            ->label('Acknowledge')
            ->color('gray')
            ->requiresConfirmation()
            ->modalHeading('Acknowledge issue')
            ->modalDescription('This records an acknowledgement for governance and audit. It does not change the verification outcome.')
            ->form([
                Textarea::make('ack_reason')
                    ->label('Reason')
                    ->required()
                    ->maxLength(160)
                    ->rows(3),
                TextInput::make('expires_at')
                    ->label('Expiry (optional)')
                    ->helperText('Optional timestamp (informational only).')
                    ->maxLength(64),
            ])
            ->action(function (array $data, array $arguments): void {
                $user = auth()->user();

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

                if (! $this->managedEnvironment instanceof ManagedEnvironment) {
                    abort(404);
                }

                $tenant = $this->managedEnvironment->fresh();

                if (! $tenant instanceof ManagedEnvironment) {
                    abort(404);
                }

                $run = $this->verificationRun();

                if (! $run instanceof OperationRun) {
                    throw new NotFoundHttpException;
                }

                $checkKey = (string) ($arguments['check_key'] ?? '');
                $ackReason = (string) ($data['ack_reason'] ?? '');
                $expiresAt = $data['expires_at'] ?? null;
                $expiresAt = is_string($expiresAt) ? $expiresAt : null;

                try {
                    app(VerificationCheckAcknowledgementService::class)->acknowledge(
                        tenant: $tenant,
                        run: $run,
                        checkKey: $checkKey,
                        ackReason: $ackReason,
                        expiresAt: $expiresAt,
                        actor: $user,
                    );
                } catch (InvalidArgumentException $e) {
                    Notification::make()
                        ->title('Unable to acknowledge')
                        ->body($e->getMessage())
                        ->danger()
                        ->send();

                    return;
                }

                Notification::make()
                    ->title('Issue acknowledged')
                    ->success()
                    ->send();
            })
            ->visible(function (array $arguments): bool {
                $user = auth()->user();

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

                if (! $this->managedEnvironment instanceof ManagedEnvironment) {
                    return false;
                }

                if (! $user->can(Capabilities::TENANT_VERIFICATION_ACKNOWLEDGE, $this->managedEnvironment)) {
                    return false;
                }

                $run = $this->verificationRun();

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

                $checkKey = trim((string) ($arguments['check_key'] ?? ''));

                if ($checkKey === '') {
                    return false;
                }

                $ackExists = VerificationCheckAcknowledgement::query()
                    ->where('operation_run_id', (int) $run->getKey())
                    ->where('check_key', $checkKey)
                    ->exists();

                if ($ackExists) {
                    return false;
                }

                $report = VerificationReportViewer::report($run);

                if (! is_array($report)) {
                    return false;
                }

                $checks = $report['checks'] ?? null;
                $checks = is_array($checks) ? $checks : [];

                foreach ($checks as $check) {
                    if (! is_array($check)) {
                        continue;
                    }

                    if (($check['key'] ?? null) !== $checkKey) {
                        continue;
                    }

                    $status = $check['status'] ?? null;

                    return is_string($status) && in_array($status, [
                        VerificationCheckStatus::Fail->value,
                        VerificationCheckStatus::Warn->value,
                    ], true);
                }

                return false;
            });
    }

    private function bootstrapRunsLabel(): string
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return '';
        }

        $runs = $this->lifecycleService()->bootstrapRunSummaries($this->onboardingSession, $this->selectedProviderConnectionId);

        if ($runs === []) {
            return '';
        }

        $activeRuns = array_filter($runs, static fn (array $run): bool => (bool) $run['is_active']);
        $failedRuns = array_filter($runs, static fn (array $run): bool => (bool) $run['is_failure'] || (bool) $run['is_partial_failure']);

        if ($activeRuns !== []) {
            return sprintf('Bootstrap is running across %d operation(s).', count($activeRuns));
        }

        if ($failedRuns !== []) {
            return sprintf('Bootstrap needs attention for %d operation(s).', count($failedRuns));
        }

        return sprintf('Bootstrap completed across %d operation(s).', count($runs));
    }

    private function touchOnboardingSessionStep(string $step): void
    {
        $user = auth()->user();

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

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return;
        }

        if ($this->onboardingSession->current_step === $step) {
            return;
        }

        try {
            $this->setOnboardingSession($this->mutationService()->mutate(
                draft: $this->onboardingSession,
                actor: $user,
                expectedVersion: $this->expectedDraftVersion(),
                incrementVersion: false,
                mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($step): void {
                    $draft->current_step = $step;
                },
            ));
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict();

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft();

            return;
        }

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingDraftUpdated->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => $this->onboardingSession->managed_environment_id !== null ? (int) $this->onboardingSession->managed_environment_id : null,
                    'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                    'current_step' => $step,
                ],
            ],
            actor: $user,
            status: 'success',
            resourceType: 'managed_environment_onboarding_session',
            resourceId: (string) $this->onboardingSession->getKey(),
        );
    }

    private function authorizeWorkspaceMutation(User $user, string $capability): void
    {
        $this->authorizeWorkspaceMember($user);

        if (! $user->can($capability, $this->workspace)) {
            abort(403);
        }
    }

    private function authorizeEditableDraft(User $user): void
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return;
        }

        $expectedVersion = $this->expectedDraftVersion();

        $this->setOnboardingSession(app(TrustedStateResolver::class)->resolveOnboardingDraft(
            $this->onboardingSessionId ?? $this->onboardingSession,
            $user,
            $this->workspace,
            app(OnboardingDraftResolver::class),
        ));

        if ($expectedVersion !== null) {
            $this->onboardingSessionVersion = $expectedVersion;
        }

        $this->authorize('update', $this->onboardingSession);

        if (! $this->canResumeDraft($this->onboardingSession)) {
            abort(404);
        }
    }

    private function trustedManagedEnvironmentForUser(User $user): ManagedEnvironment
    {
        $tenant = $this->currentManagedEnvironmentRecord();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        $tenant = $tenant->fresh();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        $tenant = app(WorkspaceContext::class)->ensureTenantAccessibleInCurrentWorkspace($tenant, $user, request());

        $this->setManagedEnvironment($tenant);

        return $tenant;
    }

    private function canResumeDraft(?ManagedEnvironmentOnboardingSession $draft): bool
    {
        if (! $draft instanceof ManagedEnvironmentOnboardingSession) {
            return false;
        }

        if (! $draft->managedEnvironment instanceof ManagedEnvironment) {
            return $this->lifecycleService()->canResumeDraft($draft);
        }

        $user = $this->currentUser();

        return app(TenantOperabilityService::class)->outcomeFor(
            tenant: $draft->managedEnvironment,
            question: TenantOperabilityQuestion::ResumeOnboardingEligibility,
            actor: $user instanceof User ? $user : null,
            workspaceId: isset($this->workspace) ? (int) $this->workspace->getKey() : null,
            lane: TenantInteractionLane::OnboardingWorkflow,
            onboardingDraft: $draft,
        )->allowed;
    }

    private function authorizeWorkspaceMember(User $user): void
    {
        $this->workspace = app(TrustedStateResolver::class)->currentWorkspaceForMember(
            $user,
            app(WorkspaceContext::class),
            request(),
        );
    }

    private function resolveWorkspaceIdForUnboundEnvironment(ManagedEnvironment $tenant): ?int
    {
        $workspaceId = DB::table('managed_environment_memberships')
            ->join('workspace_memberships', 'workspace_memberships.user_id', '=', 'managed_environment_memberships.user_id')
            ->where('managed_environment_memberships.managed_environment_id', (int) $tenant->getKey())
            ->orderBy('workspace_memberships.created_at')
            ->value('workspace_memberships.workspace_id');

        return $workspaceId === null ? null : (int) $workspaceId;
    }

    /**
     * @param  array{entra_tenant_id: string, environment: string, name: string, primary_domain?: string, notes?: string}  $data
     */
    public function identifyManagedEnvironment(array $data): void
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_IDENTIFY);

        $entraTenantId = (string) ($data['entra_tenant_id'] ?? '');
        $environmentName = (string) ($data['name'] ?? '');
        $environment = (string) ($data['environment'] ?? 'other');
        $primaryDomain = trim((string) ($data['primary_domain'] ?? ''));
        $notes = trim((string) ($data['notes'] ?? ''));

        if ($entraTenantId === '' || $environmentName === '') {
            abort(422);
        }

        if (! in_array($environment, ['prod', 'staging', 'dev', 'other'], true)) {
            abort(422);
        }

        $primaryDomain = $primaryDomain !== '' ? $primaryDomain : null;
        $notes = $notes !== '' ? $notes : null;

        $notificationTitle = 'Onboarding draft ready';
        $notificationBody = null;

        try {
            DB::transaction(function () use ($user, $entraTenantId, $environmentName, $environment, $primaryDomain, $notes, &$notificationTitle, &$notificationBody): void {
                $auditLogger = app(WorkspaceAuditLogger::class);
                $membershipManager = app(ManagedEnvironmentMembershipManager::class);
                $currentDraftId = $this->onboardingSession?->getKey();
                $sessionWasCreated = false;

                $existingTenant = ManagedEnvironment::query()
                    ->withTrashed()
                    ->where('slug', $entraTenantId)
                    ->first();

                if ($existingTenant instanceof ManagedEnvironment) {
                    if ($existingTenant->trashed() || $existingTenant->status === ManagedEnvironment::STATUS_ARCHIVED) {
                        abort(404);
                    }

                    if ($existingTenant->workspace_id === null) {
                        $resolvedWorkspaceId = $this->resolveWorkspaceIdForUnboundEnvironment($existingTenant);

                        if ($resolvedWorkspaceId === (int) $this->workspace->getKey()) {
                            $existingTenant->forceFill(['workspace_id' => $resolvedWorkspaceId])->save();
                        }
                    }

                    if ((int) $existingTenant->workspace_id !== (int) $this->workspace->getKey()) {
                        abort(404);
                    }

                    $existingTenant->forceFill([
                        'name' => $environmentName,
                        'environment' => $environment,
                        'domain' => $primaryDomain,
                        'status' => $existingTenant->status === ManagedEnvironment::STATUS_DRAFT ? ManagedEnvironment::STATUS_ONBOARDING : $existingTenant->status,
                        'metadata' => array_merge(is_array($existingTenant->metadata) ? $existingTenant->metadata : [], array_filter([
                            'notes' => $notes,
                        ], static fn ($value): bool => $value !== null)),
                    ])->save();

                    $tenant = $existingTenant;
                } else {
                    try {
                        $tenant = ManagedEnvironment::query()->create([
                            'workspace_id' => (int) $this->workspace->getKey(),
                            'name' => $environmentName,
                            'slug' => $entraTenantId,
                            'domain' => $primaryDomain,
                            'environment' => $environment,
                            'status' => ManagedEnvironment::STATUS_ONBOARDING,
                            'metadata' => array_filter([
                                'notes' => $notes,
                            ], static fn ($value): bool => $value !== null),
                        ]);
                    } catch (QueryException $exception) {
                        // Race-safe global uniqueness: if another workspace created the managed_environment_id first,
                        // treat it as deny-as-not-found.
                        $existingTenant = ManagedEnvironment::query()
                            ->withTrashed()
                            ->where('slug', $entraTenantId)
                            ->first();

                        if ($existingTenant instanceof ManagedEnvironment && (int) $existingTenant->workspace_id !== (int) $this->workspace->getKey()) {
                            abort(404);
                        }

                        if ($existingTenant instanceof ManagedEnvironment && (int) $existingTenant->workspace_id === (int) $this->workspace->getKey()) {
                            $tenant = $existingTenant;
                        } else {
                            throw $exception;
                        }
                    }
                }

                $membershipManager->grantScope(
                    tenant: $tenant,
                    actor: $user,
                    member: $user,
                    source: 'manual',
                );

                $this->selectedProviderConnectionId ??= $this->resolveDefaultProviderConnectionId($tenant);

                $session = $this->mutationService()->createOrResume(
                    workspace: $this->workspace,
                    actor: $user,
                    entraTenantId: $entraTenantId,
                    preferredDraft: $this->onboardingSession,
                    expectedVersion: $this->expectedDraftVersion(),
                    mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($tenant, $entraTenantId, $environmentName, $environment, $primaryDomain, $notes): void {
                        $draft->managed_environment_id = (int) $tenant->getKey();
                        $draft->current_step = 'identify';
                        $draft->state = array_merge($draft->state ?? [], [
                            'entra_tenant_id' => $entraTenantId,
                            'environment_name' => $environmentName,
                            'environment' => $environment,
                            'primary_domain' => $primaryDomain,
                            'notes' => $notes,
                        ]);

                        if ($this->selectedProviderConnectionId !== null) {
                            $draft->state = array_merge($draft->state ?? [], [
                                'provider_connection_id' => (int) $this->selectedProviderConnectionId,
                            ]);
                        }
                    },
                    wasCreated: $sessionWasCreated,
                );

                $didResumeExistingDraft = ! $sessionWasCreated
                    && ($currentDraftId === null || (int) $currentDraftId !== (int) $session->getKey());

                $notificationTitle = $didResumeExistingDraft
                    ? 'Existing onboarding draft resumed'
                    : 'Onboarding draft ready';
                $notificationBody = $didResumeExistingDraft
                    ? 'A resumable draft already exists for this environment. TenantAtlas reopened it instead of creating a duplicate.'
                    : null;

                $auditLogger->log(
                    workspace: $this->workspace,
                    action: ($sessionWasCreated
                        ? AuditActionId::ManagedEnvironmentOnboardingStart
                        : AuditActionId::ManagedEnvironmentOnboardingResume
                    )->value,
                    context: [
                        'metadata' => [
                            'workspace_id' => (int) $this->workspace->getKey(),
                            'tenant_db_id' => (int) $tenant->getKey(),
                            'entra_tenant_id' => $entraTenantId,
                            'environment_name' => $environmentName,
                            'onboarding_session_id' => (int) $session->getKey(),
                            'current_step' => (string) $session->current_step,
                        ],
                    ],
                    actor: $user,
                    status: 'success',
                    resourceType: 'tenant',
                    resourceId: (string) $tenant->getKey(),
                );

                $this->setManagedEnvironment($tenant);
                $this->setOnboardingSession($session);
            });
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict('The onboarding draft changed before the tenant details were saved.');

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft('The onboarding draft is no longer editable.');

            return;
        }

        $notification = Notification::make()
            ->title($notificationTitle)
            ->success();

        if (is_string($notificationBody) && $notificationBody !== '') {
            $notification->body($notificationBody);
        }

        $notification->send();

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $this->redirect(route('admin.onboarding.draft', ['onboardingDraft' => $this->onboardingSession]));
        }
    }

    public function selectProviderConnection(int $providerConnectionId): void
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_VIEW);
        $this->authorizeEditableDraft($user);

        $tenant = $this->trustedManagedEnvironmentForUser($user);

        $connection = ProviderConnection::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->whereKey($providerConnectionId)
            ->first();

        if (! $connection instanceof ProviderConnection) {
            abort(404);
        }

        $previousProviderConnectionId = $this->selectedProviderConnectionId;

        $this->selectedProviderConnectionId = (int) $connection->getKey();

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            try {
                $this->setOnboardingSession($this->mutationService()->mutate(
                    draft: $this->onboardingSession,
                    actor: $user,
                    expectedVersion: $this->expectedDraftVersion(),
                    mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($connection, $previousProviderConnectionId): void {
                        $draft->state = $this->resetDependentOnboardingStateOnConnectionChange(
                            state: array_merge($draft->state ?? [], [
                                'provider_connection_id' => (int) $connection->getKey(),
                            ]),
                            previousProviderConnectionId: $previousProviderConnectionId,
                            newProviderConnectionId: (int) $connection->getKey(),
                        );
                        $draft->current_step = 'connection';
                    },
                ));
            } catch (OnboardingDraftConflictException) {
                $this->handleDraftConflict();

                return;
            } catch (OnboardingDraftImmutableException) {
                $this->handleImmutableDraft();

                return;
            }
        }

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingProviderConnectionChanged->value,
            context: [
                'metadata' => $this->providerConnectionTargetScopeAuditMetadata($connection, [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => (int) $tenant->getKey(),
                    'onboarding_session_id' => $this->onboardingSession?->getKey(),
                ]),
            ],
            actor: $user,
            status: 'success',
            resourceType: 'provider_connection',
            resourceId: (string) $connection->getKey(),
        );

        Notification::make()
            ->title('Provider connection selected')
            ->success()
            ->send();

        $this->initializeWizardData();
    }

    /**
     * @param  array{display_name: string, connection_type?: string, client_id?: string, client_secret?: string, is_default?: bool}  $data
     */
    public function createProviderConnection(array $data): void
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE);
        $this->authorizeEditableDraft($user);

        $tenant = $this->trustedManagedEnvironmentForUser($user)->fresh();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        if ((int) $tenant->workspace_id !== (int) $this->workspace->getKey()) {
            abort(404);
        }

        $displayName = trim((string) ($data['display_name'] ?? ''));
        $requestedConnectionType = ProviderConnectionType::tryFrom(trim((string) ($data['connection_type'] ?? '')));
        $clientId = trim((string) ($data['client_id'] ?? ''));
        $clientSecret = trim((string) ($data['client_secret'] ?? ''));
        $makeDefault = (bool) ($data['is_default'] ?? false);
        $usesDedicatedCredential = $requestedConnectionType === ProviderConnectionType::Dedicated
            || $clientId !== ''
            || $clientSecret !== '';

        if ($displayName === '') {
            abort(422);
        }

        $targetScope = app(ProviderConnectionTargetScopeNormalizer::class)->normalizeInput(
            provider: 'microsoft',
            scopeKind: ProviderConnectionTargetScopeDescriptor::SCOPE_KIND_TENANT,
            scopeIdentifier: (string) $tenant->managed_environment_id,
            scopeDisplayName: $displayName,
            providerSpecificIdentity: [
                'microsoft_tenant_id' => (string) $tenant->managed_environment_id,
            ],
        );

        if ($targetScope['status'] !== ProviderConnectionTargetScopeNormalizer::STATUS_NORMALIZED) {
            throw ValidationException::withMessages([
                'new_connection.target_scope_id' => $targetScope['message'],
            ]);
        }

        if ($usesDedicatedCredential) {
            $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE_DEDICATED);
        }

        if ($usesDedicatedCredential && ($clientId === '' || $clientSecret === '')) {
            abort(422);
        }

        $wasExistingConnection = false;
        $previousConnectionType = null;

        /** @var ProviderConnection $connection */
        $connection = DB::transaction(function () use ($tenant, $displayName, $clientId, $clientSecret, $makeDefault, $usesDedicatedCredential, &$wasExistingConnection, &$previousConnectionType): ProviderConnection {
            $connection = ProviderConnection::query()
                ->where('managed_environment_id', (int) $tenant->getKey())
                ->where('provider', 'microsoft')
                ->where('entra_tenant_id', (string) $tenant->managed_environment_id)
                ->first();

            if (! $connection instanceof ProviderConnection) {
                $connection = ProviderConnection::query()->create([
                    'workspace_id' => (int) $tenant->workspace_id,
                    'managed_environment_id' => (int) $tenant->getKey(),
                    'provider' => 'microsoft',
                    'entra_tenant_id' => (string) $tenant->managed_environment_id,
                    'display_name' => $displayName,
                    'is_enabled' => true,
                    'connection_type' => ProviderConnectionType::Platform->value,
                    'consent_status' => ProviderConsentStatus::Required->value,
                    'consent_granted_at' => null,
                    'consent_last_checked_at' => null,
                    'consent_error_code' => null,
                    'consent_error_message' => null,
                    'verification_status' => ProviderVerificationStatus::Unknown->value,
                    'migration_review_required' => false,
                    'migration_reviewed_at' => null,
                    'last_error_reason_code' => ProviderReasonCodes::ProviderConsentMissing,
                    'last_error_message' => null,
                ]);
            } else {
                $wasExistingConnection = true;
                $previousConnectionType = $connection->connection_type instanceof ProviderConnectionType
                    ? $connection->connection_type
                    : ProviderConnectionType::Platform;

                $connection->forceFill([
                    'workspace_id' => (int) $tenant->workspace_id,
                    'display_name' => $displayName,
                ])->save();
            }

            if ($usesDedicatedCredential) {
                $connection = app(ProviderConnectionMutationService::class)->enableDedicatedOverride(
                    connection: $connection,
                    clientId: $clientId,
                    clientSecret: $clientSecret,
                );
            }

            if ($makeDefault) {
                $connection->makeDefault();
            }

            return $connection;
        });

        $auditLogger = app(AuditLogger::class);
        $actorId = (int) $user->getKey();
        $actorEmail = (string) $user->email;
        $actorName = (string) $user->name;

        if (! $wasExistingConnection) {
            $auditLogger->log(
                tenant: $tenant,
                action: 'provider_connection.created',
                context: [
                    'metadata' => $this->providerConnectionTargetScopeAuditMetadata($connection, [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'connection_type' => $connection->connection_type->value,
                        'source' => 'managed_environment_onboarding_wizard.create',
                    ]),
                ],
                actorId: $actorId,
                actorEmail: $actorEmail,
                actorName: $actorName,
                resourceType: 'provider_connection',
                resourceId: (string) $connection->getKey(),
                status: 'success',
            );
        }

        if ($previousConnectionType instanceof ProviderConnectionType && $previousConnectionType !== $connection->connection_type) {
            $auditLogger->log(
                tenant: $tenant,
                action: 'provider_connection.connection_type_changed',
                context: [
                    'metadata' => $this->providerConnectionTargetScopeAuditMetadata($connection, [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'from_connection_type' => $previousConnectionType->value,
                        'to_connection_type' => $connection->connection_type->value,
                        'source' => 'managed_environment_onboarding_wizard.create',
                    ]),
                ],
                actorId: $actorId,
                actorEmail: $actorEmail,
                actorName: $actorName,
                resourceType: 'provider_connection',
                resourceId: (string) $connection->getKey(),
                status: 'success',
            );
        }

        $this->selectedProviderConnectionId = (int) $connection->getKey();

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $previousProviderConnectionId = $this->onboardingSession->state['provider_connection_id'] ?? null;
            $previousProviderConnectionId = is_int($previousProviderConnectionId)
                ? $previousProviderConnectionId
                : (is_numeric($previousProviderConnectionId) ? (int) $previousProviderConnectionId : null);

            try {
                $this->setOnboardingSession($this->mutationService()->mutate(
                    draft: $this->onboardingSession,
                    actor: $user,
                    expectedVersion: $this->expectedDraftVersion(),
                    mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($connection, $previousProviderConnectionId): void {
                        $draft->state = $this->resetDependentOnboardingStateOnConnectionChange(
                            state: array_merge($draft->state ?? [], [
                                'provider_connection_id' => (int) $connection->getKey(),
                            ]),
                            previousProviderConnectionId: $previousProviderConnectionId,
                            newProviderConnectionId: (int) $connection->getKey(),
                        );
                        $draft->current_step = 'connection';
                    },
                ));
            } catch (OnboardingDraftConflictException) {
                $this->handleDraftConflict();

                return;
            } catch (OnboardingDraftImmutableException) {
                $this->handleImmutableDraft();

                return;
            }
        }

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingProviderConnectionChanged->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => (int) $tenant->getKey(),
                    'provider_connection_id' => (int) $connection->getKey(),
                    'onboarding_session_id' => $this->onboardingSession?->getKey(),
                ],
            ],
            actor: $user,
            status: 'success',
            resourceType: 'provider_connection',
            resourceId: (string) $connection->getKey(),
        );

        Notification::make()
            ->title('Provider connection created')
            ->success()
            ->send();

        $this->initializeWizardData();
    }

    private function platformAppClientId(): string
    {
        $clientId = trim((string) config('graph.client_id'));

        return $clientId !== '' ? $clientId : 'Platform app not configured';
    }

    private function canManageDedicatedOverride(): bool
    {
        return $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE_DEDICATED);
    }

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

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_VERIFICATION_START);
        $this->authorizeEditableDraft($user);

        try {
            $tenant = $this->trustedManagedEnvironmentForUser($user)->fresh();
        } catch (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
            Notification::make()
                ->title('Identify a managed environment first')
                ->warning()
                ->send();

            return;
        }

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        $connection = $this->resolveSelectedProviderConnection($tenant);

        if (! $connection instanceof ProviderConnection) {
            Notification::make()
                ->title('No provider connection selected')
                ->body('Create or select a provider connection first.')
                ->warning()
                ->send();

            return;
        }

        $result = null;

        try {
            $this->setOnboardingSession($this->mutationService()->mutate(
                draft: $this->onboardingSession,
                actor: $user,
                expectedVersion: $this->expectedDraftVersion(),
                mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($tenant, $user, $connection, &$result): void {
                    $result = app(ProviderOperationStartGate::class)->start(
                        tenant: $tenant,
                        connection: $connection,
                        operationType: 'provider.connection.check',
                        dispatcher: function (OperationRun $run) use ($tenant, $user, $connection): void {
                            ProviderConnectionHealthCheckJob::dispatch(
                                tenantId: (int) $tenant->getKey(),
                                userId: (int) $user->getKey(),
                                providerConnectionId: (int) $connection->getKey(),
                                operationRun: $run,
                            );
                        },
                        initiator: $user,
                        extraContext: [
                            'wizard' => [
                                'flow' => 'managed_environment_onboarding',
                                'step' => 'verification',
                            ],
                        ],
                    );

                    if (! $result instanceof \App\Services\Providers\ProviderOperationStartResult) {
                        throw new RuntimeException('Verification start did not return a run result.');
                    }

                    $draft->state = array_merge($draft->state ?? [], [
                        'provider_connection_id' => (int) $connection->getKey(),
                        'verification_operation_run_id' => (int) $result->run->getKey(),
                        'connection_recently_updated' => false,
                    ]);
                    $draft->current_step = 'verify';
                },
            ));
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict();

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft();

            return;
        }

        if (! $result instanceof \App\Services\Providers\ProviderOperationStartResult) {
            throw new RuntimeException('Verification start did not return a run result.');
        }

        $auditStatus = match ($result->status) {
            'started' => 'success',
            'deduped' => 'deduped',
            'scope_busy' => 'blocked',
            default => 'success',
        };

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingVerificationStart->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => (int) $tenant->getKey(),
                    'provider_connection_id' => (int) $connection->getKey(),
                    'operation_run_id' => (int) $result->run->getKey(),
                    'result' => (string) $result->status,
                ],
            ],
            actor: $user,
            status: $auditStatus,
            resourceType: 'operation_run',
            resourceId: (string) $result->run->getKey(),
        );

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            app(WorkspaceAuditLogger::class)->log(
                workspace: $this->workspace,
                action: AuditActionId::ManagedEnvironmentOnboardingVerificationPersisted->value,
                context: [
                    'metadata' => [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'tenant_db_id' => (int) $tenant->getKey(),
                        'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                        'operation_run_id' => (int) $result->run->getKey(),
                    ],
                ],
                actor: $user,
                status: 'success',
                resourceType: 'managed_environment_onboarding_session',
                resourceId: (string) $this->onboardingSession->getKey(),
            );
        }

        $notification = app(ProviderOperationStartResultPresenter::class)->notification(
            result: $result,
            blockedTitle: 'Verification blocked',
            runUrl: $this->tenantlessOperationRunUrl((int) $result->run->getKey()),
        );

        if ($result->status === 'scope_busy') {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);

            $notification->send();

            return;
        }

        if ($result->status === 'blocked') {
            $notification->send();

            return;
        }

        OpsUxBrowserEvents::dispatchRunEnqueued($this);

        if ($result->status === 'deduped') {
            $notification->send();

            return;
        }

        $notification->send();
    }

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

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

        $this->authorizeWorkspaceMember($user);
        $this->authorizeEditableDraft($user);

        $this->refreshCheckpointLifecycle();

        Notification::make()
            ->title('Verification refreshed')
            ->success()
            ->send();
    }

    /**
     * @param  array<int, mixed>  $operationTypes
     */
    public function startBootstrap(array $operationTypes): void
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMember($user);
        $this->authorizeEditableDraft($user);

        $tenant = $this->trustedManagedEnvironmentForUser($user)->fresh();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        if (! $this->verificationCanProceed()) {
            Notification::make()
                ->title('Verification required')
                ->body('Complete verification for the selected provider connection before starting bootstrap actions.')
                ->warning()
                ->send();

            return;
        }

        $connection = $this->resolveSelectedProviderConnection($tenant);

        if (! $connection instanceof ProviderConnection) {
            Notification::make()
                ->title('No provider connection selected')
                ->warning()
                ->send();

            return;
        }

        $registry = app(ProviderOperationRegistry::class);
        $types = $this->normalizeBootstrapOperationTypes($operationTypes);

        $types = array_values(array_filter(
            $types,
            static fn (string $type): bool => $type !== 'provider.connection.check' && $registry->isAllowed($type),
        ));

        foreach ($types as $operationType) {
            $capability = $this->resolveBootstrapCapability($operationType);

            if ($capability === null) {
                abort(422);
            }

            if (! $user->can($capability, $this->workspace)) {
                abort(403);
            }
        }

        if (empty($types)) {
            Notification::make()
                ->title('No bootstrap actions selected')
                ->warning()
                ->send();

            return;
        }

        $result = null;

        try {
            $this->setOnboardingSession($this->mutationService()->mutate(
                draft: $this->onboardingSession,
                actor: $user,
                expectedVersion: $this->expectedDraftVersion(),
                mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($tenant, $connection, $types, $user, &$result): void {
                    $nextOperationType = $this->nextBootstrapOperationType($draft, $types, (int) $connection->getKey());

                    if ($nextOperationType === null) {
                        $result = [
                            'status' => 'already_completed',
                            'operation_type' => null,
                            'remaining_types' => [],
                        ];

                        return;
                    }

                    $capability = $this->resolveBootstrapCapability($nextOperationType);

                    if ($capability === null) {
                        throw new RuntimeException("Unsupported bootstrap operation type: {$nextOperationType}");
                    }

                    $startResult = app(ProviderOperationStartGate::class)->start(
                        tenant: $tenant,
                        connection: $connection,
                        operationType: $nextOperationType,
                        dispatcher: function (OperationRun $run) use ($tenant, $user, $connection, $nextOperationType): void {
                            $this->dispatchBootstrapJob(
                                operationType: $nextOperationType,
                                tenantId: (int) $tenant->getKey(),
                                userId: (int) $user->getKey(),
                                providerConnectionId: (int) $connection->getKey(),
                                run: $run,
                            );
                        },
                        initiator: $user,
                        extraContext: [
                            'wizard' => [
                                'flow' => 'managed_environment_onboarding',
                                'step' => 'bootstrap',
                            ],
                            'required_capability' => $capability,
                        ],
                    );

                    $state = $draft->state ?? [];
                    $existing = $state['bootstrap_operation_runs'] ?? [];
                    $existing = is_array($existing) ? $existing : [];

                    if ($startResult->status !== 'scope_busy') {
                        $existing[$nextOperationType] = (int) $startResult->run->getKey();
                    }

                    $state['bootstrap_operation_runs'] = $existing;
                    $state['bootstrap_operation_types'] = $types;

                    $draft->state = $state;
                    $draft->current_step = 'bootstrap';

                    $remainingTypes = array_values(array_filter(
                        $types,
                        fn (string $candidate): bool => $candidate !== $nextOperationType
                            && ! $this->bootstrapOperationSucceeded($draft, $candidate, (int) $connection->getKey()),
                    ));

                    $result = [
                        'status' => $startResult->status,
                        'start_result' => $startResult,
                        'operation_type' => $nextOperationType,
                        'run' => $startResult->run,
                        'remaining_types' => $remainingTypes,
                    ];
                },
            ));
        } catch (OnboardingDraftConflictException) {
            $this->handleDraftConflict();

            return;
        } catch (OnboardingDraftImmutableException) {
            $this->handleImmutableDraft();

            return;
        }

        if (! is_array($result)) {
            throw new RuntimeException('Bootstrap start did not return a run result.');
        }

        if ($result['status'] === 'already_completed') {
            Notification::make()
                ->title('Bootstrap already completed')
                ->body('All selected bootstrap actions have already finished successfully for this provider connection.')
                ->info()
                ->send();

            return;
        }

        $operationType = (string) ($result['operation_type'] ?? '');
        $startResult = $result['start_result'] ?? null;
        $run = $result['run'] ?? null;

        if (! $startResult instanceof \App\Services\Providers\ProviderOperationStartResult || ! $run instanceof OperationRun || $operationType === '') {
            throw new RuntimeException('Bootstrap start did not return a canonical run result.');
        }

        $remainingTypes = is_array($result['remaining_types'] ?? null)
            ? array_values(array_filter($result['remaining_types'], static fn (mixed $value): bool => is_string($value) && $value !== ''))
            : [];

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $auditStatus = match ($result['status']) {
                'started' => 'success',
                'deduped' => 'deduped',
                'scope_busy' => 'blocked',
                default => 'success',
            };

            app(WorkspaceAuditLogger::class)->log(
                workspace: $this->workspace,
                action: AuditActionId::ManagedEnvironmentOnboardingBootstrapStarted->value,
                context: [
                    'metadata' => [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'tenant_db_id' => (int) $tenant->getKey(),
                        'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                        'operation_types' => $types,
                        'started_operation_type' => $operationType,
                        'operation_run_id' => (int) $run->getKey(),
                        'result' => (string) $result['status'],
                    ],
                ],
                actor: $user,
                status: $auditStatus,
                resourceType: 'managed_environment_onboarding_session',
                resourceId: (string) $this->onboardingSession->getKey(),
            );
        }

        $notification = app(ProviderOperationStartResultPresenter::class)->notification(
            result: $startResult,
            blockedTitle: 'Bootstrap action blocked',
            runUrl: $this->tenantlessOperationRunUrl((int) $run->getKey()),
            scopeBusyTitle: 'Bootstrap action busy',
            scopeBusyBody: $remainingTypes !== []
                ? 'Another provider-backed bootstrap action is already running for this provider connection. Open the active operation, then continue with the remaining bootstrap actions after it finishes.'
                : 'Another provider-backed bootstrap action is already running for this provider connection. Open the active operation for progress and next steps.',
        );

        if (in_array($result['status'], ['started', 'deduped', 'scope_busy'], true)) {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);
        }

        $notification->send();

        if ($remainingTypes !== [] && in_array($result['status'], ['started', 'deduped'], true)) {
            Notification::make()
                ->title('Continue bootstrap after this run finishes')
                ->body(sprintf('%d additional bootstrap action(s) remain selected for this provider connection.', count($remainingTypes)))
                ->info()
                ->send();
        }
    }

    private function dispatchBootstrapJob(
        string $operationType,
        int $tenantId,
        int $userId,
        int $providerConnectionId,
        OperationRun $run,
    ): void {
        match ($operationType) {
            'inventory.sync' => ProviderInventorySyncJob::dispatch(
                tenantId: $tenantId,
                userId: $userId,
                providerConnectionId: $providerConnectionId,
                operationRun: $run,
            )->afterCommit(),
            'compliance.snapshot' => ProviderComplianceSnapshotJob::dispatch(
                tenantId: $tenantId,
                userId: $userId,
                providerConnectionId: $providerConnectionId,
                operationRun: $run,
            )->afterCommit(),
            default => throw new RuntimeException("Unsupported bootstrap operation type: {$operationType}"),
        };
    }

    /**
     * @param  array<int, string>  $types
     */
    private function nextBootstrapOperationType(ManagedEnvironmentOnboardingSession $draft, array $types, int $providerConnectionId): ?string
    {
        foreach ($types as $type) {
            if (! $this->bootstrapOperationSucceeded($draft, $type, $providerConnectionId)) {
                return $type;
            }
        }

        return null;
    }

    private function bootstrapOperationSucceeded(ManagedEnvironmentOnboardingSession $draft, string $type, int $providerConnectionId): bool
    {
        $state = is_array($draft->state) ? $draft->state : [];
        $runMap = $state['bootstrap_operation_runs'] ?? [];

        if (! is_array($runMap)) {
            return false;
        }

        $runId = $runMap[$type] ?? null;

        if (! is_numeric($runId)) {
            return false;
        }

        $run = OperationRun::query()->whereKey((int) $runId)->first();

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

        $context = is_array($run->context ?? null) ? $run->context : [];
        $runProviderConnectionId = is_numeric($context['provider_connection_id'] ?? null)
            ? (int) $context['provider_connection_id']
            : null;

        if ($runProviderConnectionId !== $providerConnectionId) {
            return false;
        }

        return $run->status === OperationRunStatus::Completed->value
            && $run->outcome === OperationRunOutcome::Succeeded->value;
    }

    private function resolveBootstrapCapability(string $operationType): ?string
    {
        return $this->supportedBootstrapCapabilities()[$operationType] ?? null;
    }

    private function canStartAnyBootstrap(): bool
    {
        foreach ($this->supportedBootstrapCapabilities() as $capability) {
            if ($this->currentUserCan($capability)) {
                return true;
            }
        }

        return false;
    }

    private function currentUserCan(string $capability): bool
    {
        $user = auth()->user();

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

        return $user->can($capability, $this->workspace);
    }

    private function tenantlessOperationRunUrl(int $runId): string
    {
        return OperationRunLinks::tenantlessView($runId);
    }

    /**
     * @param  array{state: 'no_changes'|'changed', previous_report_id: int}|null  $changeIndicator
     */
    private function verificationPreviousRunUrl(?array $changeIndicator): ?string
    {
        if (! is_array($changeIndicator)) {
            return null;
        }

        $previousRunId = $changeIndicator['previous_report_id'] ?? null;

        if (! is_int($previousRunId)) {
            return null;
        }

        $previousRun = OperationRun::query()->whereKey($previousRunId)->first();

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

        if (! $this->canInspectOperationRun($previousRun)) {
            return null;
        }

        return $this->tenantlessOperationRunUrl((int) $previousRun->getKey());
    }

    /**
     * @return array{
     *   run: array<string, mixed>|null,
     *   runUrl: string|null,
     *   previousRunUrl: string|null,
     *   hasReport: bool
     * }
     */
    private function verificationTechnicalDetailsViewData(): array
    {
        $run = $this->verificationRun();

        if (! $run instanceof OperationRun) {
            return [
                'run' => null,
                'runUrl' => null,
                'previousRunUrl' => null,
                'hasReport' => false,
            ];
        }

        $report = VerificationReportViewer::report($run);
        $changeIndicator = VerificationReportChangeIndicator::forRun($run);
        $context = is_array($run->context ?? null) ? $run->context : [];
        $targetScope = $context['target_scope'] ?? [];
        $targetScope = is_array($targetScope) ? $targetScope : [];

        return [
            'run' => [
                'id' => (int) $run->getKey(),
                'type' => (string) $run->type,
                'status' => (string) $run->status,
                'outcome' => (string) $run->outcome,
                'started_at' => $run->started_at?->toJSON(),
                'updated_at' => $run->updated_at?->toJSON(),
                'completed_at' => $run->completed_at?->toJSON(),
                'target_scope' => $targetScope,
            ],
            'runUrl' => $this->verificationRunUrl(),
            'previousRunUrl' => $this->verificationPreviousRunUrl($changeIndicator),
            'hasReport' => is_array($report),
        ];
    }

    private function canInspectOperationRun(OperationRun $run): bool
    {
        $user = auth()->user();

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

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

    public function verificationSucceeded(): bool
    {
        return $this->verificationHasSucceeded();
    }

    private function verificationCanProceed(): bool
    {
        return $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession
            && $this->lifecycleService()->verificationCanProceed($this->onboardingSession, $this->selectedProviderConnectionId);
    }

    private function verificationIsBlocked(): bool
    {
        return $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession
            && $this->lifecycleService()->verificationIsBlocked($this->onboardingSession, $this->selectedProviderConnectionId);
    }

    private function canCompleteOnboarding(): bool
    {
        if (! $this->managedEnvironment instanceof ManagedEnvironment) {
            return false;
        }

        if ($this->completionSummaryEntitlementBlocked()) {
            return false;
        }

        $user = $this->currentUser();

        if (! app(TenantOperabilityService::class)->outcomeFor(
            tenant: $this->managedEnvironment,
            question: TenantOperabilityQuestion::OnboardingCompletionEligibility,
            actor: $user instanceof User ? $user : null,
            workspaceId: isset($this->workspace) ? (int) $this->workspace->getKey() : null,
            lane: TenantInteractionLane::OnboardingWorkflow,
            onboardingDraft: $this->onboardingSession,
        )->allowed) {
            return false;
        }

        if (! $this->resolveSelectedProviderConnection($this->managedEnvironment)) {
            return false;
        }

        if ($this->lifecycleState() === OnboardingLifecycleState::ReadyForActivation) {
            return true;
        }

        if (! (bool) ($this->data['override_blocked'] ?? false)) {
            return false;
        }

        if (! $this->verificationIsBlocked()) {
            return false;
        }

        return trim((string) ($this->data['override_reason'] ?? '')) !== '';
    }

    /**
     * @return array<string, mixed>
     */
    private function completionSummaryEntitlementDecision(): array
    {
        if (! isset($this->workspace) || ! $this->workspace instanceof Workspace) {
            return [];
        }

        return app(WorkspaceCommercialLifecycleResolver::class)->actionDecision(
            $this->workspace,
            WorkspaceCommercialLifecycleResolver::ACTION_MANAGED_TENANT_ACTIVATION,
        );
    }

    private function completionSummaryEntitlementBlocked(): bool
    {
        return ($this->completionSummaryEntitlementDecision()['outcome'] ?? null) === WorkspaceCommercialLifecycleResolver::OUTCOME_BLOCK;
    }

    private function completionSummaryEntitlementSummary(): string
    {
        $decision = $this->completionSummaryEntitlementDecision();
        $entitlementDecision = is_array($decision['entitlement_decision'] ?? null) ? $decision['entitlement_decision'] : [];
        $currentUsage = (int) ($entitlementDecision['current_usage'] ?? 0);
        $effectiveValue = (int) ($entitlementDecision['effective_value'] ?? 0);
        $sourceLabel = $this->completionSummaryEntitlementSourceLabel($entitlementDecision);
        $commercialSourceLabel = $this->completionSummaryCommercialSourceLabel($decision);
        $stateLabel = is_string($decision['state_label'] ?? null) ? $decision['state_label'] : 'Active paid';

        return sprintf(
            '%s - %s - %d active of %d allowed (%s, %s)',
            $this->completionSummaryEntitlementBlocked() ? 'Blocked' : 'Allowed',
            $stateLabel,
            $currentUsage,
            $effectiveValue,
            $sourceLabel,
            $commercialSourceLabel,
        );
    }

    private function completionSummaryEntitlementDetail(): string
    {
        $decision = $this->completionSummaryEntitlementDecision();
        $entitlementDecision = is_array($decision['entitlement_decision'] ?? null) ? $decision['entitlement_decision'] : [];
        $currentUsage = (int) ($entitlementDecision['current_usage'] ?? 0);
        $effectiveValue = (int) ($entitlementDecision['effective_value'] ?? 0);
        $remainingCapacity = (int) ($entitlementDecision['remaining_capacity'] ?? 0);
        $sourceLabel = $this->completionSummaryEntitlementSourceLabel($entitlementDecision);
        $rationale = is_string($decision['rationale'] ?? null) ? $decision['rationale'] : null;
        $message = sprintf(
            '%s Current usage is %d active managed environment%s out of %d allowed. Source: %s.',
            (string) ($decision['message'] ?? 'Managed-environment activation is available for this workspace commercial state.'),
            $currentUsage,
            $currentUsage === 1 ? '' : 's',
            $effectiveValue,
            $sourceLabel,
        );

        if ($remainingCapacity >= 0) {
            $message .= sprintf(' Remaining capacity: %d.', $remainingCapacity);
        }

        if ($this->completionSummaryEntitlementBlocked()) {
            $blockReason = is_string($decision['block_reason'] ?? null) ? $decision['block_reason'] : null;

            if ($blockReason !== null && $blockReason !== '') {
                $message = $blockReason;
            }
        }

        if ($rationale !== null && $rationale !== '' && ($decision['source'] ?? null) === WorkspaceCommercialLifecycleResolver::SOURCE_WORKSPACE_SETTING) {
            $message .= ' Rationale: '.$rationale;
        }

        return $message;
    }

    private function completionSummaryEntitlementColor(): string
    {
        return $this->completionSummaryEntitlementBlocked() ? 'warning' : 'success';
    }

    /**
     * @param  array<string, mixed>  $decision
     */
    private function completionSummaryEntitlementSourceLabel(array $decision): string
    {
        if (($decision['source'] ?? null) === 'workspace_override') {
            return 'workspace override';
        }

        $label = $decision['plan_profile_label'] ?? null;

        return is_string($label) && $label !== ''
            ? sprintf('%s plan profile', $label)
            : 'plan profile default';
    }

    /**
     * @param  array<string, mixed>  $decision
     */
    private function completionSummaryCommercialSourceLabel(array $decision): string
    {
        return ($decision['source'] ?? null) === WorkspaceCommercialLifecycleResolver::SOURCE_WORKSPACE_SUBSCRIPTION
            ? 'subscription-backed'
            : 'fallback-backed';
    }

    private function completionActionTooltip(): ?string
    {
        if (! $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_ACTIVATE)) {
            return 'Owner required to complete onboarding.';
        }

        if ($this->completionSummaryEntitlementBlocked()) {
            return $this->completionSummaryEntitlementDetail();
        }

        return null;
    }

    private function completionSummaryEnvironmentLine(): string
    {
        $tenant = $this->currentManagedEnvironmentRecord();

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

        $name = $tenant->name ?? '—';
        $tenantId = $tenant->graphTenantId();

        return $tenantId !== null ? "{$name} ({$tenantId})" : $name;
    }

    private function completionSummaryConnectionLabel(): string
    {
        $tenant = $this->currentManagedEnvironmentRecord();

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

        $connection = $this->resolveSelectedProviderConnection($tenant);

        if (! $connection instanceof ProviderConnection) {
            return 'Not configured';
        }

        $type = $connection->connection_type instanceof ProviderConnectionType
            ? $connection->connection_type
            : ProviderConnectionType::tryFrom((string) $connection->connection_type);

        return match ($type) {
            ProviderConnectionType::Platform => 'Platform',
            ProviderConnectionType::Dedicated => 'Dedicated',
            default => (string) ($connection->display_name ?? 'Unknown'),
        };
    }

    private function completionSummaryConnectionDetail(): string
    {
        if (! $this->managedEnvironment instanceof ManagedEnvironment) {
            return '';
        }

        $connection = $this->resolveSelectedProviderConnection($this->managedEnvironment);

        if (! $connection instanceof ProviderConnection) {
            return '';
        }

        $consentStatus = $connection->consent_status instanceof ProviderConsentStatus
            ? $connection->consent_status
            : ProviderConsentStatus::tryFrom((string) $connection->consent_status);

        $consentLabel = match ($consentStatus) {
            ProviderConsentStatus::Granted => 'Consent granted',
            ProviderConsentStatus::Failed => 'Consent failed',
            ProviderConsentStatus::Required => 'Consent required',
            ProviderConsentStatus::Revoked => 'Consent revoked',
            default => 'Consent unknown',
        };

        $parts = [$connection->display_name ?? '', $consentLabel];

        return implode(' · ', array_filter($parts, static fn (string $v): bool => $v !== ''));
    }

    private function completionSummaryConnectionSummary(): string
    {
        $label = $this->completionSummaryConnectionLabel();
        $detail = $this->completionSummaryConnectionDetail();

        if ($detail === '') {
            return $label;
        }

        return sprintf('%s - %s', $label, $detail);
    }

    private function stringValue(mixed $value): string
    {
        if ($value instanceof BackedEnum) {
            return (string) $value->value;
        }

        if (is_string($value) || is_int($value) || is_float($value) || is_bool($value)) {
            return (string) $value;
        }

        return '';
    }

    private function completionSummaryVerificationDetail(): string
    {
        $counts = $this->verificationReportCounts();

        if ($counts === null) {
            return 'Not started';
        }

        return sprintf('%d/%d checks passed', $counts['pass'], $counts['total']);
    }

    private function completionSummaryBootstrapLabel(): string
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return $this->completionSummarySelectedBootstrapTypes() === []
                ? 'Skipped'
                : 'Selected';
        }

        if ($this->completionSummaryBootstrapActionRequiredDetail() !== null) {
            return 'Action required';
        }

        $runs = $this->onboardingSession->state['bootstrap_operation_runs'] ?? null;
        $runs = is_array($runs) ? $runs : [];

        if ($runs !== []) {
            return $this->completionSummaryBootstrapCompleted()
                ? 'Completed'
                : 'Started';
        }

        return $this->completionSummarySelectedBootstrapTypes() === []
            ? 'Skipped'
            : 'Selected';
    }

    private function completionSummaryBootstrapDetail(): string
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $selectedTypes = $this->completionSummarySelectedBootstrapTypes();

            return $selectedTypes === []
                ? 'No bootstrap actions selected'
                : sprintf('%d action(s) selected', count($selectedTypes));
        }

        $runs = $this->onboardingSession->state['bootstrap_operation_runs'] ?? null;
        $runs = is_array($runs) ? $runs : [];
        $selectedTypes = $this->completionSummarySelectedBootstrapTypes();
        $actionRequiredDetail = $this->completionSummaryBootstrapActionRequiredDetail();

        if ($selectedTypes === []) {
            return 'No bootstrap actions selected';
        }

        if ($actionRequiredDetail !== null) {
            return $actionRequiredDetail;
        }

        if ($runs === []) {
            return sprintf('%d action(s) selected', count($selectedTypes));
        }

        if ($this->completionSummaryBootstrapCompleted()) {
            return sprintf('%d action(s) completed', count($runs));
        }

        if (count($runs) < count($selectedTypes)) {
            return sprintf('%d of %d action(s) started', count($runs), count($selectedTypes));
        }

        return sprintf('%d action(s) started', count($runs));
    }

    private function completionSummaryBootstrapSummary(): string
    {
        return sprintf(
            '%s - %s',
            $this->completionSummaryBootstrapLabel(),
            $this->completionSummaryBootstrapDetail(),
        );
    }

    private function completionSummaryBootstrapCompleted(): bool
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return false;
        }

        $selectedTypes = $this->completionSummarySelectedBootstrapTypes();

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

        $runs = $this->onboardingSession->state['bootstrap_operation_runs'] ?? null;
        $runs = is_array($runs) ? $runs : [];

        if ($runs === [] || count($runs) < count($selectedTypes)) {
            return false;
        }

        $runIds = array_values(array_filter(array_map(
            static fn (mixed $value): ?int => is_numeric($value) ? (int) $value : null,
            $runs,
        )));

        if (count($runIds) < count($selectedTypes)) {
            return false;
        }

        return OperationRun::query()
            ->whereIn('id', $runIds)
            ->where('status', OperationRunStatus::Completed->value)
            ->where('outcome', OperationRunOutcome::Succeeded->value)
            ->count() >= count($selectedTypes);
    }

    private function showCompletionSummaryBootstrapRecovery(): bool
    {
        return $this->completionSummaryBootstrapActionRequiredDetail() !== null;
    }

    private function completionSummaryBootstrapRecoveryMessage(): string
    {
        return 'Selected bootstrap actions must complete before activation. Return to Bootstrap to remove the selected actions and skip this optional step, or resolve the required permission and start the blocked action again.';
    }

    private function completionSummaryBootstrapColor(): string
    {
        return match ($this->completionSummaryBootstrapLabel()) {
            'Action required' => 'warning',
            'Started' => 'info',
            'Completed' => 'success',
            'Selected' => 'warning',
            default => 'gray',
        };
    }

    private function completionSummaryBootstrapActionRequiredDetail(): ?string
    {
        $reasonCode = $this->completionSummaryBootstrapReasonCode();

        if (! in_array($reasonCode, ['bootstrap_failed', 'bootstrap_partial_failure'], true)) {
            return null;
        }

        $run = $this->completionSummaryBootstrapFailedRun();

        if (! $run instanceof OperationRun) {
            return $reasonCode === 'bootstrap_partial_failure'
                ? 'A bootstrap action needs attention'
                : 'A bootstrap action failed';
        }

        $context = is_array($run->context ?? null) ? $run->context : [];
        $operatorLabel = data_get($context, 'reason_translation.operator_label');

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

        return match ($run->outcome) {
            OperationRunOutcome::PartiallySucceeded->value => 'A bootstrap action needs attention',
            OperationRunOutcome::Blocked->value => 'A bootstrap action was blocked',
            default => 'A bootstrap action failed',
        };
    }

    private function completionSummaryBootstrapReasonCode(): ?string
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return null;
        }

        $reasonCode = $this->lifecycleService()->snapshot($this->onboardingSession)['reason_code'] ?? null;

        return is_string($reasonCode) ? $reasonCode : null;
    }

    private function completionSummaryBootstrapFailedRun(): ?OperationRun
    {
        return once(function (): ?OperationRun {
            if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
                return null;
            }

            $runMap = $this->onboardingSession->state['bootstrap_operation_runs'] ?? null;

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

            $runIds = array_values(array_filter(array_map(
                static fn (mixed $value): ?int => is_numeric($value) ? (int) $value : null,
                $runMap,
            )));

            if ($runIds === []) {
                return null;
            }

            return OperationRun::query()
                ->whereIn('id', $runIds)
                ->where('status', OperationRunStatus::Completed->value)
                ->whereIn('outcome', [
                    OperationRunOutcome::Blocked->value,
                    OperationRunOutcome::Failed->value,
                    OperationRunOutcome::PartiallySucceeded->value,
                ])
                ->latest('id')
                ->first();
        });
    }

    /**
     * @return array<int, string>
     */
    private function completionSummarySelectedBootstrapTypes(): array
    {
        $selectedTypes = $this->data['bootstrap_operation_types'] ?? null;

        if (is_array($selectedTypes)) {
            $normalized = $this->normalizeBootstrapOperationTypes($selectedTypes);

            if ($normalized !== []) {
                return $normalized;
            }
        }

        if ($this->selectedBootstrapOperationTypes !== []) {
            return $this->normalizeBootstrapOperationTypes($this->selectedBootstrapOperationTypes);
        }

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return [];
        }

        $persistedTypes = $this->onboardingSession->state['bootstrap_operation_types'] ?? null;

        return is_array($persistedTypes)
            ? $this->normalizeBootstrapOperationTypes($persistedTypes)
            : [];
    }

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

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_ACTIVATE);
        $this->authorizeEditableDraft($user);

        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            abort(404);
        }

        $tenant = $this->trustedManagedEnvironmentForUser($user);

        $completionOutcome = app(TenantOperabilityService::class)->outcomeFor(
            tenant: $tenant,
            question: TenantOperabilityQuestion::OnboardingCompletionEligibility,
            actor: $user,
            workspaceId: (int) $this->workspace->getKey(),
            lane: TenantInteractionLane::OnboardingWorkflow,
            onboardingDraft: $this->onboardingSession,
        );

        if (! $completionOutcome->allowed) {
            Notification::make()
                ->title('Onboarding unavailable')
                ->body('This environment can no longer be completed from the current onboarding workflow state.')
                ->warning()
                ->send();

            return;
        }

        if ($this->completionSummaryEntitlementBlocked()) {
            Notification::make()
                ->title('Activation unavailable')
                ->body($this->completionSummaryEntitlementDetail())
                ->warning()
                ->send();

            return;
        }

        $run = $this->verificationRun();
        $verificationSucceeded = $this->verificationHasSucceeded();
        $verificationCanProceed = $this->verificationCanProceed();
        $verificationBlocked = $this->verificationIsBlocked();

        if (! $verificationCanProceed) {
            $overrideBlocked = (bool) ($this->data['override_blocked'] ?? false);

            if (! $overrideBlocked) {
                Notification::make()
                    ->title('Verification required')
                    ->body('Complete verification for the selected provider connection before completing onboarding.')
                    ->warning()
                    ->send();

                return;
            }

            if (! $verificationBlocked) {
                throw ValidationException::withMessages([
                    'data.override_blocked' => 'Verification override is only allowed when verification is blocked.',
                ]);
            }

            $overrideReason = trim((string) ($this->data['override_reason'] ?? ''));

            if ($overrideReason === '') {
                throw ValidationException::withMessages([
                    'data.override_reason' => 'Override reason is required.',
                ]);
            }
        }

        $tenant = $tenant->fresh();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        $connection = $this->resolveSelectedProviderConnection($tenant);

        if (! $connection instanceof ProviderConnection) {
            Notification::make()
                ->title('Provider connection required')
                ->body('Create or select a provider connection before completing onboarding.')
                ->warning()
                ->send();

            return;
        }

        $overrideBlocked = (bool) ($this->data['override_blocked'] ?? false);
        $overrideReason = trim((string) ($this->data['override_reason'] ?? ''));

        try {
            DB::transaction(function () use ($tenant, $user): void {
                $tenant->update(['status' => ManagedEnvironment::STATUS_ACTIVE]);

                $this->setOnboardingSession($this->mutationService()->mutate(
                    draft: $this->onboardingSession,
                    actor: $user,
                    expectedVersion: $this->expectedDraftVersion(),
                    mutator: function (ManagedEnvironmentOnboardingSession $draft): void {
                        $draft->completed_at = now();
                        $draft->cancelled_at = null;
                        $draft->current_step = 'complete';
                    },
                ));
            });
        } catch (OnboardingDraftConflictException) {
            $tenant->refresh();

            if ($tenant->status === ManagedEnvironment::STATUS_ACTIVE) {
                $tenant->update(['status' => ManagedEnvironment::STATUS_ONBOARDING]);
            }

            $this->handleDraftConflict('Completing onboarding was blocked because the onboarding draft changed.');

            return;
        } catch (OnboardingDraftImmutableException) {
            $tenant->refresh();

            if ($tenant->status === ManagedEnvironment::STATUS_ACTIVE) {
                $tenant->update(['status' => ManagedEnvironment::STATUS_ONBOARDING]);
            }

            $this->handleImmutableDraft('Completing onboarding was blocked because the onboarding draft is no longer editable.');

            return;
        }

        if ($overrideBlocked) {
            app(WorkspaceAuditLogger::class)->log(
                workspace: $this->workspace,
                action: AuditActionId::ManagedEnvironmentOnboardingActivationOverrideUsed->value,
                context: [
                    'metadata' => [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'tenant_db_id' => (int) $tenant->getKey(),
                        'onboarding_session_id' => (int) $this->onboardingSession->getKey(),
                        'verification_operation_run_id' => $run instanceof OperationRun ? (int) $run->getKey() : null,
                        'override_reason' => $overrideReason,
                    ],
                ],
                actor: $user,
                status: 'override',
                resourceType: 'managed_environment_onboarding_session',
                resourceId: (string) $this->onboardingSession->getKey(),
            );
        }

        app(WorkspaceAuditLogger::class)->log(
            workspace: $this->workspace,
            action: AuditActionId::ManagedEnvironmentOnboardingActivation->value,
            context: [
                'metadata' => [
                    'workspace_id' => (int) $this->workspace->getKey(),
                    'tenant_db_id' => (int) $tenant->getKey(),
                    'provider_connection_id' => (int) $connection->getKey(),
                    'verification_operation_run_id' => $run instanceof OperationRun ? (int) $run->getKey() : null,
                    'verification_succeeded' => $verificationSucceeded,
                    'override_blocked' => $overrideBlocked,
                    'override_reason' => $overrideBlocked ? $overrideReason : null,
                ],
            ],
            actor: $user,
            status: $overrideBlocked ? 'override' : 'success',
            resourceType: 'tenant',
            resourceId: (string) $tenant->getKey(),
        );

        $this->redirect(ManagedEnvironmentLinks::viewUrl($tenant));
    }

    private function verificationRun(): ?OperationRun
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return null;
        }

        return $this->lifecycleService()->verificationRun($this->onboardingSession);
    }

    private function verificationHasSucceeded(): bool
    {
        return $this->verificationCanProceed()
            && $this->verificationStatus() === 'ready';
    }

    private function verificationRunIsStaleForSelectedConnection(): bool
    {
        $run = $this->verificationRun();

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

        return ! $this->verificationRunMatchesSelectedConnection($run);
    }

    private function verificationRunMatchesSelectedConnection(OperationRun $run): bool
    {
        $selectedProviderConnectionId = $this->selectedProviderConnectionId;

        if ($selectedProviderConnectionId === null && $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $candidate = $this->onboardingSession->state['provider_connection_id'] ?? null;
            $selectedProviderConnectionId = $this->resolvePersistedProviderConnectionId($candidate);
        }

        if ($selectedProviderConnectionId === null) {
            return false;
        }

        $context = is_array($run->context ?? null) ? $run->context : [];
        $runProviderConnectionId = $context['provider_connection_id'] ?? null;
        $runProviderConnectionId = is_int($runProviderConnectionId)
            ? $runProviderConnectionId
            : (is_numeric($runProviderConnectionId) ? (int) $runProviderConnectionId : null);

        if ($runProviderConnectionId === null) {
            return false;
        }

        return $runProviderConnectionId === $selectedProviderConnectionId;
    }

    /**
     * @return array{is_visible: bool, reason: 'permission_blocked'|'permission_attention'|'hidden_ready'|'hidden_irrelevant'}
     */
    private function verificationAssistVisibility(): array
    {
        $tenant = $this->managedEnvironment;
        $user = $this->currentUser();
        $run = $this->verificationRun();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User || ! $user->canAccessTenant($tenant)) {
            return $this->hiddenVerificationAssistVisibility();
        }

        if (! $run instanceof OperationRun || $run->status !== OperationRunStatus::Completed->value) {
            return $this->hiddenVerificationAssistVisibility();
        }

        $report = VerificationReportViewer::report($run);

        if (! is_array($report)) {
            return $this->hiddenVerificationAssistVisibility();
        }

        return app(VerificationAssistViewModelBuilder::class)->visibility($tenant, $report);
    }

    /**
     * @return array{
     *   tenant: array{id:int,external_id:string,name:string},
     *   verification: array{overall:?string,status:?string,is_stale:bool,stale_reason:?string},
     *   overview: array{
     *     overall:string,
     *     counts: array{missing_application:int,missing_delegated:int,present:int,error:int},
     *     freshness: array{last_refreshed_at:?string,is_stale:bool}
     *   },
     *   missing_permissions: array{
     *     application: array<int, array{key:string,type:'application'|'delegated',description:?string,features:array<int,string>,status:'granted'|'missing'|'error',details:array<string,mixed>|null}>,
     *     delegated: array<int, array{key:string,type:'application'|'delegated',description:?string,features:array<int,string>,status:'granted'|'missing'|'error',details:array<string,mixed>|null}>
     *   },
     *   copy: array{application:string,delegated:string},
     *   actions: array<string, mixed>,
     *   fallback: array{has_incomplete_detail:bool,message:?string}
     * }
     */
    private function verificationAssistViewModel(): array
    {
        $tenant = $this->managedEnvironment;
        $user = $this->currentUser();
        $run = $this->verificationRun();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User || ! $user->canAccessTenant($tenant)) {
            abort(404);
        }

        if (! $run instanceof OperationRun || $run->status !== OperationRunStatus::Completed->value) {
            abort(404);
        }

        $report = VerificationReportViewer::report($run);

        if (! is_array($report)) {
            abort(404);
        }

        return app(VerificationAssistViewModelBuilder::class)->build(
            tenant: $tenant,
            verificationReport: $report,
            providerConnection: $this->resolveSelectedProviderConnection($tenant),
            verificationStatus: $this->verificationStatus(),
            isVerificationStale: $this->verificationRunIsStaleForSelectedConnection(),
            staleReason: $this->verificationAssistStaleReason(),
            canAccessProviderConnectionDiagnostics: $this->currentUserCan(Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_VIEW),
        );
    }

    private function verificationAssistStaleReason(): ?string
    {
        if (! $this->verificationRunIsStaleForSelectedConnection()) {
            return null;
        }

        return 'The selected provider connection has changed since this verification operation. Start verification again to validate the current connection.';
    }

    /**
     * @return array{is_visible: bool, reason: 'hidden_irrelevant'}
     */
    private function hiddenVerificationAssistVisibility(): array
    {
        return [
            'is_visible' => false,
            'reason' => 'hidden_irrelevant',
        ];
    }

    /**
     * @param  array<string, mixed>  $state
     * @return array<string, mixed>
     */
    private function resetDependentOnboardingStateOnConnectionChange(array $state, ?int $previousProviderConnectionId, int $newProviderConnectionId): array
    {
        if ($previousProviderConnectionId === null) {
            return $state;
        }

        if ($previousProviderConnectionId === $newProviderConnectionId) {
            return $state;
        }

        unset(
            $state['verification_operation_run_id'],
            $state['bootstrap_operation_runs'],
            $state['bootstrap_operation_types'],
        );

        $state['connection_recently_updated'] = true;

        return $state;
    }

    private function connectionRecentlyUpdated(): bool
    {
        if (! $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            return false;
        }

        return (bool) ($this->onboardingSession->state['connection_recently_updated'] ?? false);
    }

    /**
     * @return array{display_name: string, entra_tenant_id: string, uses_dedicated_override: bool, client_id: string}
     */
    private function inlineEditSelectedConnectionFill(int $providerConnectionId): array
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE);

        if (! $this->managedEnvironment instanceof ManagedEnvironment) {
            abort(404);
        }

        $connection = ProviderConnection::query()
            ->with('credential')
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $this->managedEnvironment->getKey())
            ->whereKey($providerConnectionId)
            ->first();

        if (! $connection instanceof ProviderConnection) {
            abort(404);
        }

        $payload = $connection->credential?->payload;
        $payload = is_array($payload) ? $payload : [];

        return [
            'display_name' => (string) $connection->display_name,
            'entra_tenant_id' => (string) $connection->entra_tenant_id,
            'uses_dedicated_override' => $connection->connection_type === ProviderConnectionType::Dedicated,
            'client_id' => (string) ($payload['client_id'] ?? ''),
        ];
    }

    /**
     * @param  array{display_name?: mixed, connection_type?: mixed, uses_dedicated_override?: mixed, client_id?: mixed, client_secret?: mixed}  $data
     */
    public function updateSelectedProviderConnectionInline(int $providerConnectionId, array $data): void
    {
        $user = auth()->user();

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

        $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE);

        if (! $this->managedEnvironment instanceof ManagedEnvironment) {
            abort(404);
        }

        $connection = ProviderConnection::query()
            ->with('credential')
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $this->managedEnvironment->getKey())
            ->whereKey($providerConnectionId)
            ->first();

        if (! $connection instanceof ProviderConnection) {
            abort(404);
        }

        $displayName = trim((string) ($data['display_name'] ?? ''));
        $explicitConnectionType = ProviderConnectionType::tryFrom(trim((string) ($data['connection_type'] ?? '')));
        $requestedDedicatedOverride = (bool) ($data['uses_dedicated_override'] ?? false);
        $clientId = trim((string) ($data['client_id'] ?? ''));
        $clientSecret = trim((string) ($data['client_secret'] ?? ''));
        $existingType = $connection->connection_type instanceof ProviderConnectionType
            ? $connection->connection_type
            : ProviderConnectionType::Platform;

        if ($displayName === '') {
            throw ValidationException::withMessages([
                'display_name' => 'Connection name is required.',
            ]);
        }

        $existingPayload = $connection->credential?->payload;
        $existingPayload = is_array($existingPayload) ? $existingPayload : [];
        $existingClientId = trim((string) ($existingPayload['client_id'] ?? ''));
        $targetType = $explicitConnectionType
            ?? (($requestedDedicatedOverride || $clientId !== '' || $clientSecret !== '' || $existingType === ProviderConnectionType::Dedicated)
                ? ProviderConnectionType::Dedicated
                : ProviderConnectionType::Platform);

        $changedFields = [];

        if ($displayName !== (string) $connection->display_name) {
            $changedFields[] = 'display_name';
        }

        if ($targetType !== $existingType) {
            $changedFields[] = 'connection_type';
        }

        if ($targetType === ProviderConnectionType::Dedicated) {
            $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE_DEDICATED);

            if ($clientId === '') {
                throw ValidationException::withMessages([
                    'client_id' => 'Dedicated App (client) ID is required.',
                ]);
            }

            if ($clientId !== $existingClientId) {
                $changedFields[] = 'client_id';
            }

            if (($existingType !== ProviderConnectionType::Dedicated || $clientId !== $existingClientId) && $clientSecret === '') {
                throw ValidationException::withMessages([
                    'client_secret' => 'Enter a dedicated client secret when enabling dedicated mode or changing the App (client) ID.',
                ]);
            }

            if ($clientSecret !== '') {
                $changedFields[] = 'client_secret';
            }
        }

        if ($targetType === ProviderConnectionType::Platform && $existingType === ProviderConnectionType::Dedicated) {
            $this->authorizeWorkspaceMutation($user, Capabilities::WORKSPACE_MANAGED_ENVIRONMENT_ONBOARD_CONNECTION_MANAGE_DEDICATED);
        }

        DB::transaction(function () use ($connection, $displayName, $clientId, $clientSecret, $targetType, $existingType, $existingClientId): void {
            $connection->forceFill([
                'display_name' => $displayName,
            ])->save();

            if ($targetType === ProviderConnectionType::Dedicated && $clientSecret !== '') {
                app(ProviderConnectionMutationService::class)->enableDedicatedOverride(
                    connection: $connection->fresh(),
                    clientId: $clientId,
                    clientSecret: $clientSecret,
                );
            }

            if ($targetType === ProviderConnectionType::Dedicated && $existingType === ProviderConnectionType::Dedicated && $clientSecret === '' && $clientId !== '' && $clientId === $existingClientId) {
                return;
            }

            if ($targetType === ProviderConnectionType::Platform && $existingType === ProviderConnectionType::Dedicated) {
                app(ProviderConnectionMutationService::class)->revertToPlatform($connection->fresh());
            }
        });

        if (in_array('connection_type', $changedFields, true)) {
            app(AuditLogger::class)->log(
                tenant: $this->managedEnvironment,
                action: 'provider_connection.connection_type_changed',
                context: [
                    'metadata' => $this->providerConnectionTargetScopeAuditMetadata($connection, [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'from_connection_type' => $existingType->value,
                        'to_connection_type' => $targetType->value,
                        'source' => 'managed_environment_onboarding_wizard.inline_edit',
                    ]),
                ],
                actorId: (int) $user->getKey(),
                actorEmail: (string) $user->email,
                actorName: (string) $user->name,
                resourceType: 'provider_connection',
                resourceId: (string) $connection->getKey(),
                status: 'success',
            );
        }

        if ($changedFields !== []) {
            app(AuditLogger::class)->log(
                tenant: $this->managedEnvironment,
                action: 'provider_connection.updated',
                context: [
                    'metadata' => $this->providerConnectionTargetScopeAuditMetadata($connection, [
                        'workspace_id' => (int) $this->workspace->getKey(),
                        'fields' => app(ProviderConnectionTargetScopeNormalizer::class)->auditFieldNames($changedFields),
                        'connection_type' => $targetType->value,
                        'source' => 'managed_environment_onboarding_wizard.inline_edit',
                    ]),
                ],
                actorId: (int) $user->getKey(),
                actorEmail: (string) $user->email,
                actorName: (string) $user->name,
                resourceType: 'provider_connection',
                resourceId: (string) $connection->getKey(),
                status: 'success',
            );
        }

        if ($this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            try {
                $this->setOnboardingSession($this->mutationService()->mutate(
                    draft: $this->onboardingSession,
                    actor: $user,
                    expectedVersion: $this->expectedDraftVersion(),
                    mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($connection): void {
                        $state = is_array($draft->state) ? $draft->state : [];

                        unset(
                            $state['verification_operation_run_id'],
                            $state['bootstrap_operation_runs'],
                            $state['bootstrap_operation_types'],
                        );

                        $state['connection_recently_updated'] = true;

                        $draft->state = array_merge($state, [
                            'provider_connection_id' => (int) $connection->getKey(),
                        ]);
                    },
                ));
            } catch (OnboardingDraftConflictException) {
                $this->handleDraftConflict();

                return;
            } catch (OnboardingDraftImmutableException) {
                $this->handleImmutableDraft();

                return;
            }
        }

        Notification::make()
            ->title('Connection updated')
            ->success()
            ->send();

        $this->initializeWizardData();
    }

    /**
     * @return array<string, string>
     */
    private function bootstrapOperationOptions(): array
    {
        $registry = app(ProviderOperationRegistry::class);
        $supportedTypes = array_keys($this->supportedBootstrapCapabilities());

        return collect($registry->all())
            ->filter(fn (array $definition, string $type): bool => in_array($type, $supportedTypes, true))
            ->mapWithKeys(fn (array $definition, string $type): array => [$type => (string) ($definition['label'] ?? $type)])
            ->all();
    }

    private function resolveDefaultProviderConnectionId(ManagedEnvironment $tenant): ?int
    {
        $id = ProviderConnection::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->where('is_default', true)
            ->orderByDesc('id')
            ->value('id');

        if (is_int($id)) {
            return $id;
        }

        $fallback = ProviderConnection::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->orderByDesc('id')
            ->value('id');

        return is_int($fallback) ? $fallback : null;
    }

    private function resolveSelectedProviderConnection(ManagedEnvironment $tenant): ?ProviderConnection
    {
        $providerConnectionId = $this->selectedProviderConnectionId;

        if (! is_int($providerConnectionId) && $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $candidate = $this->onboardingSession->state['provider_connection_id'] ?? null;
            $providerConnectionId = is_int($candidate) ? $candidate : null;
        }

        if (! is_int($providerConnectionId)) {
            $providerConnectionId = $this->resolveDefaultProviderConnectionId($tenant);
        }

        if (! is_int($providerConnectionId)) {
            return null;
        }

        return ProviderConnection::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->whereKey($providerConnectionId)
            ->first();
    }

    private function resolvePersistedProviderConnectionId(mixed $providerConnectionId): ?int
    {
        $providerConnectionId = is_int($providerConnectionId)
            ? $providerConnectionId
            : (is_numeric($providerConnectionId) ? (int) $providerConnectionId : null);

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

        $tenantId = $this->managedEnvironment?->getKey();

        if (! is_int($tenantId) && $this->onboardingSession instanceof ManagedEnvironmentOnboardingSession) {
            $tenantId = is_numeric($this->onboardingSession->managed_environment_id) ? (int) $this->onboardingSession->managed_environment_id : null;
        }

        if (! is_int($tenantId)) {
            return null;
        }

        $exists = ProviderConnection::query()
            ->whereKey($providerConnectionId)
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->where('managed_environment_id', $tenantId)
            ->exists();

        return $exists ? $providerConnectionId : null;
    }
}
