<?php

declare(strict_types=1);

use App\Filament\Resources\FindingResource;
use App\Filament\Resources\FindingResource\Pages\ListFindings;
use App\Filament\Widgets\ManagedEnvironment\FindingStatsOverview;
use App\Models\Finding;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

it('uses badge-formatted finding type labels instead of raw enum values', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    Finding::factory()->for($tenant)->create([
        'finding_type' => Finding::FINDING_TYPE_PERMISSION_POSTURE,
        'status' => Finding::STATUS_NEW,
    ]);

    Livewire::test(ListFindings::class)
        ->assertSee('Permission posture');
});

it('shows subject display name as an early visible column', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    $component = Livewire::test(ListFindings::class);
    $table = $component->instance()->getTable();
    $columns = array_keys($table->getVisibleColumns());

    $subjectIndex = array_search('subject_display_name', $columns);
    $statusIndex = array_search('status', $columns);

    expect($subjectIndex)->toBeLessThan($statusIndex);
});

it('places severity column before governance in column order', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    $component = Livewire::test(ListFindings::class);
    $columns = array_keys($component->instance()->getTable()->getVisibleColumns());

    $severityIndex = array_search('severity', $columns);
    $governanceIndex = array_search('governance_validity', $columns);

    expect($severityIndex)->toBeLessThan($governanceIndex);
});

it('renders the finding stats overview widget above the findings table', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    Livewire::test(ListFindings::class)
        ->assertOk()
        ->assertSeeLivewire(FindingStatsOverview::class);
});

it('returns correct finding stats counts for current tenant', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    Finding::factory()->for($tenant)->create([
        'status' => Finding::STATUS_NEW,
        'severity' => Finding::SEVERITY_LOW,
    ]);

    Finding::factory()->for($tenant)->create([
        'status' => Finding::STATUS_IN_PROGRESS,
        'severity' => Finding::SEVERITY_HIGH,
        'due_at' => now()->subDay(),
    ]);

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

    Finding::factory()->for($tenant)->create([
        'status' => Finding::STATUS_RESOLVED,
        'severity' => Finding::SEVERITY_LOW,
    ]);

    $stats = FindingResource::findingStatsForCurrentTenant();

    expect($stats['open'])->toBe(2);
    expect($stats['overdue'])->toBe(1);
    expect($stats['high_severity'])->toBe(1);
    expect($stats['risk_accepted'])->toBe(1);
    expect($stats['total'])->toBe(4);
});

it('segments findings with quick-tabs for needs-action, overdue, risk-accepted, and resolved', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'manager');
    $this->actingAs($user);
    Filament::setTenant($tenant, true);

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

    $overdue = Finding::factory()->for($tenant)->create([
        'status' => Finding::STATUS_TRIAGED,
        'due_at' => now()->subDays(2),
    ]);

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

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

    $list = Livewire::test(ListFindings::class);

    // All tab shows everything
    $list->assertCanSeeTableRecords([$open, $overdue, $riskAccepted, $resolved]);

    // Needs action tab shows open findings
    $list->set('activeTab', 'needs_action')
        ->assertCanSeeTableRecords([$open, $overdue])
        ->assertCanNotSeeTableRecords([$riskAccepted, $resolved]);

    // Overdue tab shows only overdue open findings
    $list->set('activeTab', 'overdue')
        ->assertCanSeeTableRecords([$overdue])
        ->assertCanNotSeeTableRecords([$open, $riskAccepted, $resolved]);

    // Risk accepted tab
    $list->set('activeTab', 'risk_accepted')
        ->assertCanSeeTableRecords([$riskAccepted])
        ->assertCanNotSeeTableRecords([$open, $overdue, $resolved]);

    // Resolved tab
    $list->set('activeTab', 'resolved')
        ->assertCanSeeTableRecords([$resolved])
        ->assertCanNotSeeTableRecords([$open, $overdue, $riskAccepted]);
});
