<?php

declare(strict_types=1);

use App\Filament\Pages\Monitoring\AuditLog as AuditLogPage;
use App\Models\AuditLog;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Livewire\Livewire;

it('shows finding audit history to authorized viewers and preserves drill-down links for accessible findings', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $finding = Finding::factory()->for($tenant)->create();

    $audit = AuditLog::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'actor_email' => 'owner@example.com',
        'actor_name' => 'Owner',
        'actor_type' => 'human',
        'action' => 'finding.resolved',
        'status' => 'success',
        'resource_type' => 'finding',
        'resource_id' => (string) $finding->getKey(),
        'target_label' => 'Drift finding #'.$finding->getKey(),
        'summary' => 'Finding resolved for Drift finding #'.$finding->getKey(),
        'metadata' => [
            'finding_id' => (int) $finding->getKey(),
            'before_status' => Finding::STATUS_TRIAGED,
            'after_status' => Finding::STATUS_RESOLVED,
        ],
        'recorded_at' => now(),
    ]);

    $this->actingAs($user);
    Filament::setTenant(null, true);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    Livewire::withQueryParams(['event' => (int) $audit->getKey()])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertCanSeeTableRecords([$audit])
        ->assertSet('selectedAuditLogId', (int) $audit->getKey())
        ->assertSee('Drift finding #'.$finding->getKey())
        ->assertActionVisible('open_selected_audit_target');
});

it('keeps deleted findings readable while suppressing finding drill-down links', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $finding = Finding::factory()->for($tenant)->create();
    $findingId = (int) $finding->getKey();
    $finding->delete();

    $audit = AuditLog::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'actor_email' => 'owner@example.com',
        'actor_name' => 'Owner',
        'actor_type' => 'human',
        'action' => 'finding.closed',
        'status' => 'success',
        'resource_type' => 'finding',
        'resource_id' => (string) $findingId,
        'target_label' => 'Permission posture finding #'.$findingId,
        'summary' => 'Finding closed for Permission posture finding #'.$findingId,
        'metadata' => [
            'finding_id' => $findingId,
            'before_status' => Finding::STATUS_REOPENED,
            'after_status' => Finding::STATUS_CLOSED,
            'closed_reason' => 'duplicate',
        ],
        'recorded_at' => now(),
    ]);

    $this->actingAs($user);
    Filament::setTenant(null, true);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    Livewire::withQueryParams(['event' => (int) $audit->getKey()])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertCanSeeTableRecords([$audit])
        ->assertSet('selectedAuditLogId', (int) $audit->getKey())
        ->assertSee('Permission posture finding #'.$findingId)
        ->assertActionDoesNotExist('open_selected_audit_target');
});

it('does not render internal audit bookkeeping metadata in the inspection view', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $finding = Finding::factory()->for($tenant)->resolved()->create();

    $audit = AuditLog::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'actor_email' => 'owner@example.com',
        'actor_name' => 'Owner',
        'actor_type' => 'human',
        'action' => 'finding.closed',
        'status' => 'success',
        'resource_type' => 'finding',
        'resource_id' => (string) $finding->getKey(),
        'target_label' => 'Drift finding #'.$finding->getKey(),
        'summary' => 'Finding closed for Drift finding #'.$finding->getKey(),
        'metadata' => [
            'finding_id' => (int) $finding->getKey(),
            'before_status' => Finding::STATUS_RESOLVED,
            'after_status' => Finding::STATUS_CLOSED,
            '_actor_type' => 'hidden-actor-marker',
            '_dedupe_key' => 'internal-bookkeeping-marker',
        ],
        'recorded_at' => now(),
    ]);

    $this->actingAs($user);
    Filament::setTenant(null, true);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    Livewire::withQueryParams(['event' => (int) $audit->getKey()])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertCanSeeTableRecords([$audit])
        ->assertSet('selectedAuditLogId', (int) $audit->getKey())
        ->assertDontSee('_dedupe_key')
        ->assertDontSee('internal-bookkeeping-marker')
        ->assertDontSee('_actor_type')
        ->assertDontSee('hidden-actor-marker');
});

it('hides finding audit rows for tenants outside the viewer entitlement scope', function (): void {
    [$user, $tenantA] = createUserWithTenant(role: 'owner');

    $tenantB = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
    ]);

    $findingA = Finding::factory()->for($tenantA)->create();
    $findingB = Finding::factory()->for($tenantB)->create();

    $visible = AuditLog::query()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
        'managed_environment_id' => (int) $tenantA->getKey(),
        'actor_email' => 'owner@example.com',
        'actor_name' => 'Owner',
        'actor_type' => 'human',
        'action' => 'finding.triaged',
        'status' => 'success',
        'resource_type' => 'finding',
        'resource_id' => (string) $findingA->getKey(),
        'target_label' => 'Drift finding #'.$findingA->getKey(),
        'summary' => 'Finding triaged for Drift finding #'.$findingA->getKey(),
        'metadata' => [
            'finding_id' => (int) $findingA->getKey(),
            'before_status' => Finding::STATUS_NEW,
            'after_status' => Finding::STATUS_TRIAGED,
        ],
        'recorded_at' => now(),
    ]);

    $hidden = AuditLog::query()->create([
        'workspace_id' => (int) $tenantB->workspace_id,
        'managed_environment_id' => (int) $tenantB->getKey(),
        'actor_email' => 'owner@example.com',
        'actor_name' => 'Owner',
        'actor_type' => 'human',
        'action' => 'finding.reopened',
        'status' => 'success',
        'resource_type' => 'finding',
        'resource_id' => (string) $findingB->getKey(),
        'target_label' => 'Drift finding #'.$findingB->getKey(),
        'summary' => 'Finding reopened for Drift finding #'.$findingB->getKey(),
        'metadata' => [
            'finding_id' => (int) $findingB->getKey(),
            'before_status' => Finding::STATUS_RESOLVED,
            'after_status' => Finding::STATUS_REOPENED,
        ],
        'recorded_at' => now(),
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenantA->workspace_id])
        ->get(route('admin.monitoring.audit-log').'?event='.(int) $hidden->getKey())
        ->assertSuccessful()
        ->assertDontSee('Finding reopened for Drift finding #'.$findingB->getKey());

    $this->actingAs($user);
    Filament::setTenant(null, true);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id);

    Livewire::withQueryParams(['event' => (int) $hidden->getKey()])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertSet('selectedAuditLogId', null)
        ->assertCanSeeTableRecords([$visible])
        ->assertCanNotSeeTableRecords([$hidden]);
});
