<?php

declare(strict_types=1);

use App\Filament\Resources\FindingExceptionResource\Pages\ViewFindingException;
use App\Models\Finding;
use App\Models\User;
use App\Services\Findings\FindingExceptionService;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;

uses(RefreshDatabase::class);

function findingExceptionHeaderActions(Testable $component): array
{
    $instance = $component->instance();

    if ($instance->getCachedHeaderActions() === []) {
        $instance->cacheInteractsWithHeaderActions();
    }

    return $instance->getCachedHeaderActions();
}

function findingExceptionHeaderNames(Testable $component): array
{
    return collect(findingExceptionHeaderActions($component))
        ->reject(static fn ($action): bool => $action instanceof ActionGroup)
        ->map(static fn ($action): ?string => $action instanceof Action ? $action->getName() : null)
        ->filter()
        ->values()
        ->all();
}

it('keeps finding navigation out of the header while preserving renewal and revocation actions', function (): void {
    [$requester, $tenant] = createUserWithTenant(role: 'owner');
    $approver = User::factory()->create();
    createUserWithTenant(tenant: $tenant, user: $approver, role: 'owner', workspaceRole: 'manager');

    $finding = Finding::factory()->for($tenant)->create([
        'status' => Finding::STATUS_RISK_ACCEPTED,
    ]);

    /** @var FindingExceptionService $service */
    $service = app(FindingExceptionService::class);

    $requested = $service->request($finding, $tenant, $requester, [
        'owner_user_id' => (int) $requester->getKey(),
        'request_reason' => 'Existing compensating controls remain in place.',
        'review_due_at' => now()->addDays(7)->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
    ]);

    $exception = $service->approve($requested, $approver, [
        'effective_from' => now()->subDay()->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
        'approval_reason' => 'Accepted while remediation is scheduled.',
    ]);

    $this->actingAs($requester);
    Filament::setTenant($tenant, true);

    $component = Livewire::test(ViewFindingException::class, ['record' => $exception->getKey()])
        ->assertActionVisible('renew_exception')
        ->assertActionVisible('revoke_exception')
        ->assertActionExists('revoke_exception', fn (Action $action): bool => $action->isConfirmationRequired())
        ->assertSee('Related context')
        ->assertSee('Approval queue')
        ->assertSee('Open finding');

    expect(findingExceptionHeaderNames($component))
        ->toEqualCanonicalizing(['renew_exception', 'revoke_exception'])
        ->not->toContain('open_finding', 'open_approval_queue');
});
