<?php

declare(strict_types=1);

use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Livewire\Livewire;

function spec314FindingException(ManagedEnvironment $environment, User $user, string $reason): FindingException
{
    $finding = Finding::factory()
        ->for($environment)
        ->riskAccepted()
        ->create([
            'workspace_id' => (int) $environment->workspace_id,
            'subject_external_id' => str()->slug($reason),
        ]);

    return FindingException::query()->create([
        'workspace_id' => (int) $environment->workspace_id,
        'managed_environment_id' => (int) $environment->getKey(),
        'finding_id' => (int) $finding->getKey(),
        'requested_by_user_id' => (int) $user->getKey(),
        'owner_user_id' => (int) $user->getKey(),
        'status' => FindingException::STATUS_PENDING,
        'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
        'request_reason' => $reason,
        'requested_at' => now()->subDay(),
        'review_due_at' => now()->addDay(),
        'evidence_summary' => ['reference_count' => 0],
    ]);
}

it('Spec314 finding exceptions queue sidebar entry is workspace wide', function (): void {
    $environmentA = ManagedEnvironment::factory()->active()->create([
        'name' => 'Queue Environment A',
        'external_id' => 'queue-environment-a',
    ]);
    [$user, $environmentA] = createUserWithTenant(tenant: $environmentA, role: 'owner');

    $environmentB = ManagedEnvironment::factory()->active()->create([
        'workspace_id' => (int) $environmentA->workspace_id,
        'name' => 'Queue Environment B',
        'external_id' => 'queue-environment-b',
    ]);
    createUserWithTenant(tenant: $environmentB, user: $user, role: 'owner');

    $exceptionA = spec314FindingException($environmentA, $user, 'Spec314 Queue A');
    $exceptionB = spec314FindingException($environmentB, $user, 'Spec314 Queue B');

    Filament::setTenant($environmentA, true);

    $url = FindingExceptionsQueue::getUrl(panel: 'admin');

    expect($url)->not->toContain('tenant=');

    $this->actingAs($user);
    setAdminPanelContext();
    session()->put(WorkspaceContext::SESSION_KEY, (int) $environmentA->workspace_id);
    session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
        (string) $environmentA->workspace_id => (int) $environmentA->getKey(),
    ]);

    Livewire::actingAs($user)
        ->test(FindingExceptionsQueue::class)
        ->assertCanSeeTableRecords([$exceptionA, $exceptionB]);

    $this->get($url)
        ->assertOk()
        ->assertSee(__('localization.shell.no_environment_selected'))
        ->assertDontSee(__('localization.shell.environment_scope').': Queue Environment A');
});

it('Spec314 finding exceptions queue ignores stale environment table filters on clean entry', function (): void {
    $environmentA = ManagedEnvironment::factory()->active()->create();
    [$user, $environmentA] = createUserWithTenant(tenant: $environmentA, role: 'owner');

    $environmentB = ManagedEnvironment::factory()->active()->create([
        'workspace_id' => (int) $environmentA->workspace_id,
    ]);
    createUserWithTenant(tenant: $environmentB, user: $user, role: 'owner');

    $exceptionA = spec314FindingException($environmentA, $user, 'Spec314 Queue stale A');
    $exceptionB = spec314FindingException($environmentB, $user, 'Spec314 Queue stale B');

    $this->actingAs($user);
    setAdminPanelContext();
    session()->put(WorkspaceContext::SESSION_KEY, (int) $environmentA->workspace_id);

    $component = Livewire::actingAs($user)->test(FindingExceptionsQueue::class);
    $filtersSessionKey = $component->instance()->getTableFiltersSessionKey();

    session()->put($filtersSessionKey, [
        'managed_environment_id' => ['value' => (string) $environmentA->getKey()],
    ]);

    $this->get(FindingExceptionsQueue::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertSee(__('localization.shell.no_environment_selected'));

    expect(data_get(session()->get($filtersSessionKey, []), 'managed_environment_id.value'))->toBeNull();

    Livewire::actingAs($user)
        ->test(FindingExceptionsQueue::class)
        ->assertCanSeeTableRecords([$exceptionA, $exceptionB]);
});
