<?php

declare(strict_types=1);

use App\Filament\Pages\Governance\DecisionRegister;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Services\Findings\FindingExceptionService;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->browser()->timeout(20_000);

uses(RefreshDatabase::class);

function spec265ApprovedFindingException(ManagedEnvironment $tenant, User $requester): FindingException
{
    $approver = User::factory()->create();
    createUserWithTenant(
        tenant: $tenant,
        user: $approver,
        role: 'owner',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $finding = Finding::factory()->for($tenant)->create([
        'workspace_id' => (int) $tenant->workspace_id,
        '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' => 'Spec265 browser smoke request.',
        'review_due_at' => now()->addDays(7)->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
    ]);

    return $service->approve($requested, $approver, [
        'effective_from' => now()->subDay()->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
        'approval_reason' => 'Spec265 browser smoke approval.',
    ]);
}

function spec265SmokeLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect = ''): string
{
    return route('admin.local.smoke-login', array_filter([
        'email' => $user->email,
        'tenant' => $tenant->external_id,
        'workspace' => $tenant->workspace->slug,
        'redirect' => $redirect,
    ], static fn (?string $value): bool => filled($value)));
}

it('smokes the decision register continuity to the existing exception detail page', function (): void {
    [$user, $tenant] = createUserWithTenant(
        role: 'owner',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $exceptionWithProof = spec265ApprovedFindingException($tenant, $user);
    spec265ApprovedFindingException($tenant, $user);

    $run = OperationRun::factory()->forTenant($tenant)->create([
        'type' => 'tenant.evidence.snapshot.generate',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Succeeded->value,
        'completed_at' => now(),
    ]);

    $snapshot = EvidenceSnapshot::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'operation_run_id' => (int) $run->getKey(),
        'status' => EvidenceSnapshotStatus::Active->value,
        'completeness_state' => EvidenceCompletenessState::Complete->value,
        'summary' => ['finding_count' => 1],
        'generated_at' => now(),
    ]);

    $exceptionWithProof->forceFill(['evidence_summary' => ['reference_count' => 1]])->save();
    $exceptionWithProof->evidenceReferences()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'source_type' => 'evidence_snapshot',
        'source_id' => (string) $snapshot->getKey(),
        'label' => 'Current evidence snapshot',
        'summary_payload' => [],
    ]);

    $decisionRegisterUrl = DecisionRegister::getUrl(panel: 'admin', parameters: [
        'environment_id' => (string) $tenant->getKey(),
    ]);

    visit(spec265SmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit($decisionRegisterUrl)
        ->waitForText('Decision register')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Environment filter:')
        ->assertSee($tenant->name)
        ->assertSee('Visible rows: 2')
        ->assertSee('1 proof item')
        ->assertSee('View evidence')
        ->assertSee('View operation')
        ->assertSee('No linked proof')
        ->assertSee('No operation linked')
        ->click('View evidence')
        ->waitForText('Snapshot')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit($decisionRegisterUrl)
        ->waitForText('Decision register')
        ->click('View operation')
        ->waitForText('Operation #'.((int) $run->getKey()))
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit($decisionRegisterUrl)
        ->waitForText('Decision register')
        ->assertSeeIn('tbody tr.fi-ta-row:first-of-type', $tenant->name)
        ->click('tbody tr.fi-ta-row:first-of-type')
        ->waitForText('Opened from the workspace decision register')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Back to decision register')
        ->assertSee('Renew exception')
        ->assertSee('Revoke exception')
        ->click('Back to decision register')
        ->waitForText('Decision register')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Environment filter:')
        ->assertSee($tenant->name)
        ->assertSee('Visible rows: 2');
});
