<?php

declare(strict_types=1);

use App\Models\Finding;
use App\Models\User;
use App\Services\Findings\FindingWorkflowService;
use App\Support\Audit\AuditActionId;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('keeps canonical findings workflow behavior after removing the backfill runtime surfaces', function (): void {
    [$owner, $tenant] = createUserWithTenant(role: 'owner');
    $assignee = User::factory()->create();
    createUserWithTenant(tenant: $tenant, user: $assignee, role: 'operator');

    $service = app(FindingWorkflowService::class);
    $finding = $this->makeFindingForWorkflow($tenant, Finding::STATUS_NEW, [
        'owner_user_id' => null,
        'assignee_user_id' => null,
        'sla_days' => 14,
        'due_at' => now()->addDays(14),
    ]);

    $triaged = $service->triage($finding, $tenant, $owner);
    $assigned = $service->assign(
        finding: $triaged,
        tenant: $tenant,
        actor: $owner,
        assigneeUserId: (int) $assignee->getKey(),
        ownerUserId: (int) $owner->getKey(),
    );
    $inProgress = $service->startProgress($assigned, $tenant, $owner);
    $resolved = $service->resolve($inProgress, $tenant, $owner, Finding::RESOLVE_REASON_REMEDIATED);
    $riskAccepted = $service->riskAccept(
        $this->makeFindingForWorkflow($tenant, Finding::STATUS_NEW),
        $tenant,
        $owner,
        Finding::CLOSE_REASON_ACCEPTED_RISK,
    );

    expect($triaged->status)->toBe(Finding::STATUS_TRIAGED)
        ->and($triaged->triaged_at)->not->toBeNull()
        ->and((int) $assigned->owner_user_id)->toBe((int) $owner->getKey())
        ->and((int) $assigned->assignee_user_id)->toBe((int) $assignee->getKey())
        ->and($assigned->sla_days)->toBe(14)
        ->and($assigned->due_at)->not->toBeNull()
        ->and($inProgress->status)->toBe(Finding::STATUS_IN_PROGRESS)
        ->and($inProgress->in_progress_at)->not->toBeNull()
        ->and($resolved->status)->toBe(Finding::STATUS_RESOLVED)
        ->and($resolved->resolved_reason)->toBe(Finding::RESOLVE_REASON_REMEDIATED)
        ->and($riskAccepted->status)->toBe(Finding::STATUS_RISK_ACCEPTED)
        ->and($riskAccepted->closed_reason)->toBe(Finding::CLOSE_REASON_ACCEPTED_RISK);

    expect($this->latestFindingAudit($triaged, AuditActionId::FindingTriaged))->not->toBeNull()
        ->and($this->latestFindingAudit($assigned, AuditActionId::FindingAssigned))->not->toBeNull()
        ->and($this->latestFindingAudit($inProgress, AuditActionId::FindingInProgress))->not->toBeNull()
        ->and($this->latestFindingAudit($resolved, AuditActionId::FindingResolved))->not->toBeNull()
        ->and($this->latestFindingAudit($riskAccepted, AuditActionId::FindingRiskAccepted))->not->toBeNull();
});
