<?php

declare(strict_types=1);

use App\Filament\Resources\BaselineSnapshotResource\Pages\ListBaselineSnapshots;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\Workspace;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

function baselineSnapshotSummary(int $content, int $meta, int $gaps): array
{
    return [
        'total_items' => $content + $meta,
        'fidelity_counts' => [
            'content' => $content,
            'meta' => $meta,
        ],
        'gaps' => [
            'count' => $gaps,
            'by_reason' => $gaps > 0 ? ['missing_evidence' => $gaps] : [],
        ],
    ];
}

function baselineSnapshotFilterIndicatorLabels($component): array
{
    return collect($component->instance()->getTable()->getFilterIndicators())
        ->map(fn ($indicator): string => (string) $indicator->getLabel())
        ->all();
}

it('filters baseline snapshots by baseline, lifecycle, and captured date inside the current workspace', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    session([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]);

    $baselineA = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Device Compliance',
    ]);

    $baselineB = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Device Configuration',
    ]);

    $otherWorkspace = Workspace::factory()->create();

    $otherWorkspaceBaseline = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $otherWorkspace->getKey(),
        'name' => 'Other Workspace Baseline',
    ]);

    $matching = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baselineA->getKey(),
        'lifecycle_state' => 'complete',
        'captured_at' => now()->subDay(),
        'summary_jsonb' => baselineSnapshotSummary(3, 0, 2),
    ]);

    $wrongLifecycle = BaselineSnapshot::factory()->incomplete()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baselineA->getKey(),
        'captured_at' => now()->subDay(),
        'summary_jsonb' => baselineSnapshotSummary(3, 0, 0),
    ]);

    $wrongBaseline = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baselineB->getKey(),
        'captured_at' => now()->subDay(),
        'summary_jsonb' => baselineSnapshotSummary(2, 1, 1),
    ]);

    $outsideWindow = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baselineA->getKey(),
        'captured_at' => now()->subDays(10),
        'summary_jsonb' => baselineSnapshotSummary(2, 0, 2),
    ]);

    $otherWorkspaceSnapshot = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $otherWorkspace->getKey(),
        'baseline_profile_id' => (int) $otherWorkspaceBaseline->getKey(),
        'captured_at' => now()->subDay(),
        'summary_jsonb' => baselineSnapshotSummary(4, 0, 3),
    ]);

    $component = Livewire::actingAs($user)
        ->test(ListBaselineSnapshots::class)
        ->filterTable('baseline_profile_id', (string) $baselineA->getKey())
        ->filterTable('lifecycle_state', 'complete')
        ->set('tableFilters.captured_at.from', now()->subDays(2)->toDateString())
        ->set('tableFilters.captured_at.until', now()->toDateString())
        ->assertCanSeeTableRecords([$matching])
        ->assertCanNotSeeTableRecords([$wrongLifecycle, $wrongBaseline, $outsideWindow, $otherWorkspaceSnapshot]);

    expect(baselineSnapshotFilterIndicatorLabels($component))
        ->toContain('Captured from '.now()->subDays(2)->toFormattedDateString())
        ->toContain('Captured until '.now()->toFormattedDateString());
});

it('clears baseline snapshot filters back to the workspace-owned list', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    session([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]);

    $baseline = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
    ]);

    $withGaps = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baseline->getKey(),
        'lifecycle_state' => 'complete',
        'captured_at' => now()->subHour(),
        'summary_jsonb' => baselineSnapshotSummary(2, 0, 1),
    ]);

    $building = BaselineSnapshot::factory()->building()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $baseline->getKey(),
        'captured_at' => now()->subDays(5),
        'summary_jsonb' => baselineSnapshotSummary(2, 0, 0),
    ]);

    $component = Livewire::actingAs($user)
        ->test(ListBaselineSnapshots::class)
        ->filterTable('lifecycle_state', 'complete')
        ->set('tableFilters.captured_at.from', now()->subDays(2)->toDateString())
        ->set('tableFilters.captured_at.until', now()->toDateString())
        ->assertCanSeeTableRecords([$withGaps])
        ->assertCanNotSeeTableRecords([$building]);

    $component
        ->set('tableFilters.lifecycle_state.value', null)
        ->set('tableFilters.captured_at.from', null)
        ->set('tableFilters.captured_at.until', null)
        ->assertCanSeeTableRecords([$withGaps, $building]);
});
