<?php

declare(strict_types=1);

use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
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 Livewire\Livewire;

it('stores the selected provider_connection_id in the onboarding session', 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());

    $this->actingAs($user);

    $entraTenantId = '33333333-3333-3333-3333-333333333333';

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class);

    $component->call('identifyManagedEnvironment', [
        'entra_tenant_id' => $entraTenantId,
        'environment' => 'prod',
        'name' => 'Acme',
    ]);

    $tenant = ManagedEnvironment::query()->where('slug', $entraTenantId)->firstOrFail();

    $connection = ProviderConnection::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => $entraTenantId,
        'display_name' => 'Acme (onboarding)',
        'is_default' => true,
    ]);

    $component->call('selectProviderConnection', (int) $connection->getKey());

    $session = ManagedEnvironmentOnboardingSession::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('entra_tenant_id', $entraTenantId)
        ->whereNull('completed_at')
        ->firstOrFail();

    expect($session->state['provider_connection_id'] ?? null)->toBe((int) $connection->getKey());
});

it('prevents selecting a provider connection bound to a different managed environment', 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());

    $this->actingAs($user);

    $entraTenantId = '44444444-4444-4444-4444-444444444444';

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class);

    $component->call('identifyManagedEnvironment', [
        'entra_tenant_id' => $entraTenantId,
        'environment' => 'prod',
        'name' => 'Primary ManagedEnvironment',
    ]);

    $primaryTenant = ManagedEnvironment::query()->where('slug', $entraTenantId)->firstOrFail();

    $otherTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => '55555555-5555-5555-5555-555555555555',
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);

    $otherConnection = ProviderConnection::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $otherTenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => (string) $otherTenant->managed_environment_id,
        'display_name' => 'Other tenant connection',
        'is_default' => true,
    ]);

    expect((int) $otherConnection->managed_environment_id)->not->toBe((int) $primaryTenant->getKey());

    $component
        ->call('selectProviderConnection', (int) $otherConnection->getKey())
        ->assertStatus(404);
});

it('ignores forged onboarding session and managed environment state when selecting a provider connection', 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());

    $this->actingAs($user);

    $entraTenantId = '64646464-6464-6464-6464-646464646464';

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class);

    $component->call('identifyManagedEnvironment', [
        'entra_tenant_id' => $entraTenantId,
        'environment' => 'prod',
        'name' => 'Primary ManagedEnvironment',
    ]);

    $primarySession = ManagedEnvironmentOnboardingSession::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('entra_tenant_id', $entraTenantId)
        ->firstOrFail();

    $otherTenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => '65656565-6565-6565-6565-656565656565',
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);

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

    $otherConnection = ProviderConnection::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $otherTenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => (string) $otherTenant->managed_environment_id,
        'display_name' => 'Forged tenant connection',
        'is_default' => true,
    ]);

    $component
        ->set('onboardingSession', $otherDraft)
        ->set('managedEnvironment', $otherTenant)
        ->call('selectProviderConnection', (int) $otherConnection->getKey())
        ->assertStatus(404);

    $primarySession->refresh();
    $otherDraft->refresh();

    expect($primarySession->state['provider_connection_id'] ?? null)->toBeNull()
        ->and($otherDraft->state['provider_connection_id'] ?? null)->toBeNull();
});
