<?php

declare(strict_types=1);

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

it('shows a safe non-editable summary for completed drafts', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'status' => 'completed',
        'state' => [
            'entra_tenant_id' => '11111111-1111-1111-1111-111111111111',
            'environment_name' => 'Completed Contoso',
            'environment' => 'prod',
        ],
    ]);

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

it('shows a safe non-editable summary for cancelled drafts', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'status' => 'cancelled',
        'state' => [
            'entra_tenant_id' => '22222222-2222-2222-2222-222222222222',
            'environment_name' => 'Cancelled Contoso',
            'environment' => 'prod',
        ],
    ]);

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

it('shows a linked environment action when the onboarding draft has a viewable tenant record', function (): void {
    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'name' => 'Linked Onboarding ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

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

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

it('keeps the linked environment action visible for entitled operators on archived environment summaries', function (): void {
    $tenant = ManagedEnvironment::factory()->archived()->create([
        'name' => 'Archived Summary ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

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

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->assertActionVisible('view_linked_environment')
        ->assertActionHasLabel('view_linked_environment', 'View environment (Archived)');
});

it('cancels a resumable onboarding draft through the confirmed header action', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => '33333333-3333-3333-3333-333333333333',
            'environment_name' => 'Draft To Cancel',
        ],
    ]);

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->mountAction('cancel_onboarding_draft')
        ->callMountedAction()
        ->assertNotified('Onboarding draft cancelled')
        ->assertRedirect(route('admin.onboarding.draft', ['onboardingDraft' => (int) $draft->getKey()]));

    $draft->refresh();

    expect($draft->cancelled_at)->not->toBeNull()
        ->and($draft->isResumable())->toBeFalse()
        ->and($draft->current_step)->toBe('cancelled');

    $this->actingAs($user)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => (int) $draft->getKey()]))
        ->assertSuccessful()
        ->assertSee('This onboarding draft is Cancelled.')
        ->assertDontSee('Cancel draft');

    expect(AuditLog::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('action', AuditActionId::ManagedEnvironmentOnboardingCancelled->value)
        ->where('resource_id', (string) $draft->getKey())
        ->exists())->toBeTrue();
});

it('deletes a non-resumable onboarding draft from the header action', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'status' => 'cancelled',
        'state' => [
            'entra_tenant_id' => '66666666-6666-6666-6666-666666666666',
            'environment_name' => 'Draft To Delete',
        ],
    ]);

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->assertActionVisible('back_to_workspace')
        ->assertActionVisible('delete_onboarding_draft_header')
        ->mountAction('delete_onboarding_draft_header')
        ->callMountedAction()
        ->assertNotified('Onboarding draft deleted')
        ->assertRedirect(route('admin.onboarding'));

    expect(AuditLog::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('action', AuditActionId::ManagedEnvironmentOnboardingDeleted->value)
        ->where('resource_id', (string) $draft->getKey())
        ->exists())->toBeTrue();

    $this->assertDatabaseMissing('managed_environment_onboarding_sessions', [
        'id' => (int) $draft->getKey(),
    ]);

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

it('keeps cancelled drafts out of the landing redirect and picker flow', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $activeDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => '44444444-4444-4444-4444-444444444444',
            'environment_name' => 'Active Draft',
        ],
    ]);

    createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'status' => 'cancelled',
        'state' => [
            'entra_tenant_id' => '55555555-5555-5555-5555-555555555555',
            'environment_name' => 'Cancelled Draft',
        ],
    ]);

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

it('uses workflow-contextual onboarding wording on landing and draft routes', function (): void {
    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $firstDraft = createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => '44444444-1111-1111-1111-111111111111',
            'environment_name' => 'First Draft',
        ],
    ]);

    createOnboardingDraft([
        'workspace' => $workspace,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => '55555555-1111-1111-1111-111111111111',
            'environment_name' => 'Second Draft',
        ],
    ]);

    $this->actingAs($user)
        ->get(route('admin.onboarding'))
        ->assertSuccessful()
        ->assertSee('Resume onboarding')
        ->assertDontSee('Resume onboarding draft');

    $this->actingAs($user)
        ->get(route('admin.onboarding.draft', ['onboardingDraft' => $firstDraft->getKey()]))
        ->assertSuccessful()
        ->assertSee('Choose onboarding draft')
        ->assertDontSee('All onboarding drafts');
});

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

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

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

    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => 'aaaaaaaa-1111-1111-1111-111111111111',
        'name' => 'Activation Ready ManagedEnvironment',
    ]);

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

    $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' => [],
                ],
            ]),
        ],
    ]);

    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(),
        ],
    ]);

    $this->actingAs($user)
        ->followingRedirects()
        ->get(route('admin.onboarding'))
        ->assertSuccessful()
        ->assertSee('Complete onboarding')
        ->assertDontSee('Activate tenant')
        ->assertDontSeeText('Restore environment')
        ->assertDontSeeText('Archive tenant')
        ->assertSee('After completion');
});

it('warns instead of completing onboarding when the workflow is not ready', function (): void {
    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'name' => 'Verification Pending ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

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

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentOnboardingWizard::class, [
            'onboardingDraft' => (int) $draft->getKey(),
        ])
        ->call('completeOnboarding')
        ->assertNotified('Verification required');

    $tenant->refresh();
    $draft->refresh();

    expect($tenant->status)->toBe(ManagedEnvironment::STATUS_ONBOARDING)
        ->and($draft->completed_at)->toBeNull()
        ->and($draft->current_step)->toBe('connection');
});

it('returns a linked onboarding tenant to draft when its last onboarding draft is cancelled', function (): void {
    $tenant = ManagedEnvironment::factory()->onboarding()->create([
        'name' => 'Cancelled Linked ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

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

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

    $tenant->refresh();

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

    expect(AuditLog::query()
        ->where('workspace_id', (int) $tenant->workspace_id)
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('action', AuditActionId::TenantReturnedToDraft->value)
        ->exists())->toBeTrue();
});
