<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Verification\VerificationReportWriter;
use App\Support\Workspaces\WorkspaceContext;
use Livewire\Livewire;

it('allows another authorized operator to load a shared draft and see attribution', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
        'name' => 'Shared ManagedEnvironment',
    ]);
    $creator = User::factory()->create(['name' => 'Draft Creator']);
    $manager = User::factory()->create(['name' => 'Workspace Manager']);

    createUserWithTenant(
        tenant: $tenant,
        user: $creator,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    createUserWithTenant(
        tenant: $tenant,
        user: $manager,
        role: 'manager',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $creator,
        'updated_by' => $manager,
        'state' => [
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'environment_name' => (string) $tenant->name,
        ],
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($manager)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertSuccessful()
        ->assertSee('Onboarding draft')
        ->assertSee('Draft Creator')
        ->assertSee('Workspace Manager');
});

it('allows a manager to cancel a shared onboarding draft', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $creator = User::factory()->create();
    $manager = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $creator,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    createUserWithTenant(
        tenant: $tenant,
        user: $manager,
        role: 'manager',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $creator,
        'updated_by' => $creator,
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    Livewire::actingAs($manager)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->mountAction('cancel_onboarding_draft')
        ->callMountedAction()
        ->assertNotified('Onboarding draft cancelled');

    expect($draft->fresh()->isCancelled())->toBeTrue();
});

it('cancels the route-bound draft even when public onboarding draft state is forged', function (): void {
    $workspace = Workspace::factory()->create();
    $primaryTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $secondaryTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $user = User::factory()->create();

    createUserWithTenant(
        tenant: $primaryTenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $user->tenants()->syncWithoutDetaching([
        $secondaryTenant->getKey() => ['role' => 'owner'],
    ]);

    $primaryDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $primaryTenant,
        'started_by' => $user,
        'updated_by' => $user,
    ]);

    $secondaryDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $secondaryTenant,
        'started_by' => $user,
        'updated_by' => $user,
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $primaryDraft->getKey(),
        ])
        ->set('onboardingSession', $secondaryDraft)
        ->set('managedEnvironment', $secondaryTenant)
        ->mountAction('cancel_onboarding_draft')
        ->callMountedAction()
        ->assertNotified('Onboarding draft cancelled');

    expect($primaryDraft->fresh()->isCancelled())->toBeTrue()
        ->and($secondaryDraft->fresh()?->isCancelled())->toBeFalse();
});

it('keeps rendering the route-bound draft after forged continuity state is refreshed', function (): void {
    $workspace = Workspace::factory()->create();
    $primaryTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
        'name' => 'Primary Continuity ManagedEnvironment',
        'managed_environment_id' => '35353535-3535-3535-3535-353535353535',
    ]);
    $secondaryTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
        'name' => 'Secondary Continuity ManagedEnvironment',
        'managed_environment_id' => '36363636-3636-3636-3636-363636363636',
    ]);
    $user = User::factory()->create(['name' => 'Continuity Owner']);

    createUserWithTenant(
        tenant: $primaryTenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $user->tenants()->syncWithoutDetaching([
        $secondaryTenant->getKey() => ['role' => 'owner'],
    ]);

    $primaryDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $primaryTenant,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => (string) $primaryTenant->managed_environment_id,
            'environment_name' => (string) $primaryTenant->name,
        ],
    ]);

    $secondaryDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $secondaryTenant,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => (string) $secondaryTenant->managed_environment_id,
            'environment_name' => (string) $secondaryTenant->name,
        ],
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $primaryDraft->getKey(),
        ])
        ->set('onboardingSession', $secondaryDraft)
        ->set('managedEnvironment', $secondaryTenant)
        ->call('refreshCheckpointLifecycle')
        ->assertSet('onboardingSessionId', (int) $primaryDraft->getKey())
        ->assertSet('managedEnvironmentId', (int) $primaryTenant->getKey())
        ->assertSee('Primary Continuity ManagedEnvironment')
        ->assertDontSee('Secondary Continuity ManagedEnvironment');
});

it('resolves the cancel draft header action as enabled for managers with cancel capability', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $user = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $user,
        role: 'manager',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $user,
        'updated_by' => $user,
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->assertActionVisible('cancel_onboarding_draft')
        ->assertActionEnabled('cancel_onboarding_draft');
});

it('keeps destructive draft actions confirmation protected and capability gated', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $manager = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $manager,
        role: 'manager',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $resumableDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $manager,
        'updated_by' => $manager,
    ]);
    $cancelledDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $manager,
        'updated_by' => $manager,
        'status' => 'cancelled',
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    Livewire::actingAs($manager)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $resumableDraft->getKey(),
        ])
        ->assertActionExists('cancel_onboarding_draft', fn (\Filament\Actions\Action $action): bool => $action->isConfirmationRequired())
        ->assertActionEnabled('cancel_onboarding_draft');

    Livewire::actingAs($manager)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $cancelledDraft->getKey(),
        ])
        ->assertActionExists('delete_onboarding_draft_header', fn (\Filament\Actions\Action $action): bool => $action->isConfirmationRequired())
        ->assertActionEnabled('delete_onboarding_draft_header');
});

it('returns 404 for non-members when requesting a shared onboarding draft', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $creator = User::factory()->create();
    $nonMember = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $creator,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $creator,
        'updated_by' => $creator,
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($nonMember)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertNotFound();
});

it('returns 403 for readonly members even when they have tenant access', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);
    $readonly = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $readonly,
        role: 'readonly',
        workspaceRole: 'readonly',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $readonly,
        'updated_by' => $readonly,
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($readonly)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertForbidden();
});

it('keeps readiness routes hidden from non-members and wrong workspaces while capability denials stay forbidden', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
        'name' => 'Readiness Authorization ManagedEnvironment',
    ]);
    $owner = User::factory()->create();
    $nonMember = User::factory()->create();
    $wrongWorkspaceUser = User::factory()->create();
    $readonly = User::factory()->create();
    $wrongWorkspace = Workspace::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $owner,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    createUserWithTenant(
        tenant: $tenant,
        user: $readonly,
        role: 'readonly',
        workspaceRole: 'readonly',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    \App\Models\WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $wrongWorkspace->getKey(),
        'user_id' => (int) $wrongWorkspaceUser->getKey(),
        'role' => 'owner',
    ]);

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $owner,
        'updated_by' => $owner,
        'state' => [
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'environment_name' => (string) $tenant->name,
        ],
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($nonMember)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertNotFound();

    session()->put(WorkspaceContext::SESSION_KEY, (int) $wrongWorkspace->getKey());

    $this->actingAs($wrongWorkspaceUser)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertNotFound();

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($readonly)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertForbidden();
});

it('returns 403 for readonly members on cancelled draft summaries so delete controls never render', function (): void {
    $workspace = Workspace::factory()->create();
    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_DRAFT,
    ]);
    $readonly = User::factory()->create();

    createUserWithTenant(
        tenant: $tenant,
        user: $readonly,
        role: 'readonly',
        workspaceRole: 'readonly',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $readonly,
        'updated_by' => $readonly,
        'status' => 'cancelled',
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($readonly)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertForbidden();
});

it('returns 404 for workspace members without linked archived tenant entitlement', function (): void {
    $workspace = Workspace::factory()->create();
    $archivedTenant = ManagedEnvironment::factory()->archived()->create([
        'workspace_id' => (int) $workspace->getKey(),
    ]);
    $creator = User::factory()->create();
    $workspaceOwner = User::factory()->create();

    createUserWithTenant(
        tenant: $archivedTenant,
        user: $creator,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    \App\Models\WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $workspaceOwner->getKey(),
        'role' => 'owner',
    ]);
    createUserWithTenant(
        tenant: ManagedEnvironment::factory()->create(['workspace_id' => (int) $workspace->getKey()]),
        user: $workspaceOwner,
        role: 'owner',
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $archivedTenant,
        'started_by' => $creator,
        'updated_by' => $creator,
        'state' => [
            'entra_tenant_id' => (string) $archivedTenant->managed_environment_id,
            'environment_name' => (string) $archivedTenant->name,
        ],
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($workspaceOwner)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertNotFound();
});

it('shows a non-editable summary for entitled operators when the linked environment is already archived', function (): void {
    $workspace = Workspace::factory()->create();
    $archivedTenant = ManagedEnvironment::factory()->archived()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'name' => 'Archived Linked ManagedEnvironment',
    ]);
    $user = User::factory()->create();

    createUserWithTenant(
        tenant: $archivedTenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $archivedTenant,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => (string) $archivedTenant->managed_environment_id,
            'environment_name' => (string) $archivedTenant->name,
        ],
    ]);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $this->actingAs($user)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
        ->assertSuccessful()
        ->assertSee('This onboarding draft is Draft.')
        ->assertSee('Completed, cancelled, and lifecycle-locked drafts remain viewable, but they cannot return to editable wizard mode.')
        ->assertDontSee('Cancel draft')
        ->assertSee('View environment');
});

it('keeps complete onboarding disabled for managers without activation capability', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'workspace_id' => (int) $workspace->getKey(),
    ]);

    createUserWithTenant(
        tenant: $tenant,
        user: $user,
        role: 'manager',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $connection = ProviderConnection::factory()->platform()->consentGranted()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => (string) $tenant->managed_environment_id,
        'is_default' => true,
        'consent_status' => 'granted',
    ]);

    $run = OperationRun::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'type' => 'provider.connection.check',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Succeeded->value,
        'context' => [
            'provider_connection_id' => (int) $connection->getKey(),
            'target_scope' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
                'entra_tenant_name' => (string) $tenant->name,
            ],
            'verification_report' => VerificationReportWriter::build('provider.connection.check', [
                [
                    'key' => 'consent',
                    'title' => 'Required application permissions',
                    'status' => 'pass',
                    'severity' => 'low',
                    'blocking' => false,
                    'reason_code' => 'ok',
                    'message' => 'Consent is ready.',
                    'evidence' => [],
                    'next_steps' => [],
                ],
            ]),
        ],
    ]);

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $user,
        'updated_by' => $user,
        'current_step' => 'bootstrap',
        'state' => [
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'environment_name' => (string) $tenant->name,
            'provider_connection_id' => (int) $connection->getKey(),
            'verification_operation_run_id' => (int) $run->getKey(),
        ],
    ]);

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->assertSee('Complete onboarding')
        ->call('completeOnboarding')
        ->assertForbidden();
});

it('allows owners to complete activation-ready onboarding drafts', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'workspace_id' => (int) $workspace->getKey(),
    ]);

    createUserWithTenant(
        tenant: $tenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $connection = ProviderConnection::factory()->platform()->consentGranted()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => (string) $tenant->managed_environment_id,
        'is_default' => true,
        'consent_status' => 'granted',
    ]);

    $run = OperationRun::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'type' => 'provider.connection.check',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Succeeded->value,
        'context' => [
            'provider_connection_id' => (int) $connection->getKey(),
            'target_scope' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
                'entra_tenant_name' => (string) $tenant->name,
            ],
            'verification_report' => VerificationReportWriter::build('provider.connection.check', [
                [
                    'key' => 'consent',
                    'title' => 'Required application permissions',
                    'status' => 'pass',
                    'severity' => 'low',
                    'blocking' => false,
                    'reason_code' => 'ok',
                    'message' => 'Consent is ready.',
                    'evidence' => [],
                    'next_steps' => [],
                ],
            ]),
        ],
    ]);

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $user,
        'updated_by' => $user,
        'current_step' => 'bootstrap',
        'state' => [
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'environment_name' => (string) $tenant->name,
            'provider_connection_id' => (int) $connection->getKey(),
            'verification_operation_run_id' => (int) $run->getKey(),
        ],
    ]);

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->assertSee('Complete onboarding')
        ->call('completeOnboarding')
        ->assertRedirect(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant));

    $tenant->refresh();

    expect($tenant->status)->toBe(ManagedEnvironment::STATUS_ACTIVE);
});
