<?php

use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
use App\Jobs\ProviderComplianceSnapshotJob;
use App\Jobs\ProviderConnectionHealthCheckJob;
use App\Jobs\ProviderInventorySyncJob;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Livewire\Livewire;

uses(RefreshDatabase::class);

it('returns scope-busy semantics for onboarding verification when another run is active for the same connection scope', function (): void {
    Bus::fake();

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

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

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

    $tenantGuid = '10101010-1010-1010-1010-101010101010';

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class);
    $component->call('identifyManagedEnvironment', [
        'entra_tenant_id' => $tenantGuid,
        'environment' => 'prod',
        'name' => 'Acme',
        'primary_domain' => 'acme.example',
        'notes' => 'Provider start test',
    ]);

    $tenant = ManagedEnvironment::query()->forTenant($tenantGuid)->firstOrFail();

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

    OperationRun::query()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'user_id' => (int) $user->getKey(),
        'initiator_name' => $user->name,
        'type' => 'inventory.sync',
        'status' => 'queued',
        'outcome' => 'pending',
        'run_identity_hash' => sha1('busy-onboarding-'.(string) $connection->getKey()),
        'context' => [
            'provider_connection_id' => (int) $connection->getKey(),
        ],
    ]);

    $component->set('selectedProviderConnectionId', (int) $connection->getKey());
    $component->call('startVerification');

    expect(OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('type', 'provider.connection.check')
        ->count())->toBe(0);

    Bus::assertNotDispatched(ProviderConnectionHealthCheckJob::class);
});

it('serializes onboarding bootstrap so only one selected provider-backed action starts at a time', function (): void {
    Bus::fake();

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

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

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

    $tenantGuid = '20202020-2020-2020-2020-202020202020';

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class);
    $component->call('identifyManagedEnvironment', [
        'entra_tenant_id' => $tenantGuid,
        'environment' => 'prod',
        'name' => 'Acme',
        'primary_domain' => 'acme.example',
        'notes' => 'Provider start test',
    ]);

    $tenant = ManagedEnvironment::query()->forTenant($tenantGuid)->firstOrFail();

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

    spec283SeedRequirementRows($tenant, ['permissions.intune_configuration', 'permissions.intune_apps']);

    $verificationRun = OperationRun::query()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'user_id' => (int) $user->getKey(),
        'initiator_name' => $user->name,
        'type' => 'provider.connection.check',
        'status' => 'completed',
        'outcome' => 'succeeded',
        'run_identity_hash' => sha1('verify-ok-bootstrap-provider-start-'.(string) $connection->getKey()),
        'context' => [
            'provider_connection_id' => (int) $connection->getKey(),
        ],
    ]);

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

    $session->update([
        'state' => array_merge($session->state ?? [], [
            'provider_connection_id' => (int) $connection->getKey(),
            'verification_operation_run_id' => (int) $verificationRun->getKey(),
        ]),
    ]);

    $component->call('startBootstrap', ['inventory_sync', 'compliance.snapshot']);

    $inventoryRun = OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('type', 'inventory.sync')
        ->latest('id')
        ->firstOrFail();

    expect(OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('type', 'compliance.snapshot')
        ->count())->toBe(0);

    $inventoryRun->forceFill([
        'status' => 'completed',
        'outcome' => 'succeeded',
    ])->save();

    $component->call('startBootstrap', ['inventory.sync', 'compliance.snapshot']);

    expect(OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('type', 'compliance.snapshot')
        ->count())->toBe(1);

    Bus::assertDispatchedTimes(ProviderInventorySyncJob::class, 1);
    Bus::assertDispatchedTimes(ProviderComplianceSnapshotJob::class, 1);
});
