<?php

declare(strict_types=1);

use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\ManagedEnvironmentPermission;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Verification\VerificationReportWriter;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;

describe('Onboarding wizard UI enforcement', function () {
    it('denies identifyManagedEnvironment for readonly workspace members', function (): void {
        $workspace = Workspace::factory()->create();
        $user = User::factory()->create();

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

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

        Livewire::actingAs($user)
            ->test(ManagedEnvironmentOnboardingWizard::class)
            ->assertForbidden();
    });

    it('denies dedicated provider connection creation for manager members', 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,
            'current_step' => 'connection',
            'state' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
                'tenant_name' => (string) $tenant->name,
            ],
        ]);

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

        Livewire::actingAs($user)
            ->test(ManagedEnvironmentOnboardingWizard::class, [
                'onboardingDraft' => (int) $draft->getKey(),
            ])
            ->call('createProviderConnection', [
                'display_name' => 'Acme connection',
                'client_id' => '00000000-0000-0000-0000-000000000000',
                'client_secret' => 'super-secret',
                'is_default' => true,
            ])
            ->assertForbidden();
    });

    it('allows manager members to start verification for an existing onboarding session', function (): void {
        Queue::fake();

        $workspace = Workspace::factory()->create();
        $user = User::factory()->create();

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

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

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

        $connection = ProviderConnection::factory()->create([
            'workspace_id' => (int) $workspace->getKey(),
            'managed_environment_id' => (int) $tenant->getKey(),
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
        ]);

        ManagedEnvironmentOnboardingSession::query()->create([
            'workspace_id' => (int) $workspace->getKey(),
            'managed_environment_id' => (int) $tenant->getKey(),
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'current_step' => 'connection',
            'state' => [
                'provider_connection_id' => (int) $connection->getKey(),
            ],
            'started_by_user_id' => (int) $user->getKey(),
            'updated_by_user_id' => (int) $user->getKey(),
        ]);

        $draft = ManagedEnvironmentOnboardingSession::query()
            ->where('workspace_id', (int) $workspace->getKey())
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->firstOrFail();

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

        $run = OperationRun::query()
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->where('type', 'provider.connection.check')
            ->latest('id')
            ->first();

        expect($run)->not->toBeNull();

        Queue::assertNothingPushed();
    });

    it('returns 403 for in-scope members missing onboarding capability on assist-backed drafts', function (): void {
        $configured = array_merge(
            config('intune_permissions.permissions', []),
            config('entra_permissions.permissions', []),
        );

        $permissionKeys = array_values(array_filter(array_map(static function (mixed $permission): ?string {
            if (! is_array($permission)) {
                return null;
            }

            $key = $permission['key'] ?? null;

            return is_string($key) && trim($key) !== '' ? trim($key) : null;
        }, $configured)));

        if ($permissionKeys === []) {
            test()->markTestSkipped('No configured required permissions found.');
        }

        [$user, $tenant] = createUserWithTenant(
            role: 'operator',
            workspaceRole: 'operator',
            ensureDefaultMicrosoftProviderConnection: false,
        );

        $workspace = $tenant->workspace()->firstOrFail();

        foreach ($permissionKeys as $key) {
            ManagedEnvironmentPermission::query()->create([
                'managed_environment_id' => (int) $tenant->getKey(),
                'workspace_id' => (int) $workspace->getKey(),
                'permission_key' => $key,
                'status' => 'granted',
                'details' => ['source' => 'db'],
                'last_checked_at' => now()->subDays(45),
            ]);
        }

        $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' => 'permissions.admin_consent',
                        'title' => 'Required application permissions',
                        'status' => 'warn',
                        'severity' => 'medium',
                        'blocking' => false,
                        'reason_code' => ProviderReasonCodes::ProviderPermissionRefreshFailed,
                        'message' => 'Stored permission data needs review.',
                        'evidence' => [],
                        'next_steps' => [],
                    ],
                ]),
            ],
        ]);

        $draft = ManagedEnvironmentOnboardingSession::query()->create([
            'workspace_id' => (int) $workspace->getKey(),
            'managed_environment_id' => (int) $tenant->getKey(),
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'current_step' => 'verify',
            'state' => [
                'provider_connection_id' => (int) $connection->getKey(),
                'verification_operation_run_id' => (int) $run->getKey(),
            ],
            'started_by_user_id' => (int) $user->getKey(),
            'updated_by_user_id' => (int) $user->getKey(),
        ]);

        $this->actingAs($user)
            ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
            ->get(route('admin.onboarding.draft', ['onboardingDraft' => (int) $draft->getKey()]))
            ->assertForbidden();
    });

    it('returns 403 when a manager tries to complete onboarding without owner 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,
                'tenant_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(),
            ])
            ->call('completeOnboarding')
            ->assertForbidden();
    });
});
