<?php

declare(strict_types=1);

use App\Models\AuditLog;
use App\Models\OperationRun;
use App\Services\OperationRunService;
use App\Support\Operations\ExecutionAuthorityMode;
use App\Support\Operations\ExecutionDenialReasonCode;
use App\Support\Operations\QueuedExecutionContext;
use App\Support\Operations\QueuedExecutionLegitimacyDecision;
use App\Support\Verification\VerificationReportSchema;

it('writes a blocked terminal audit trail with execution denial context', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $run = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'initiator_name' => $user->name,
        'type' => 'provider.connection.check',
        'status' => 'queued',
        'outcome' => 'pending',
        'summary_counts' => [
            'total' => '4',
            'bogus_key' => 'ignored',
        ],
    ]);

    $context = new QueuedExecutionContext(
        run: $run,
        operationType: 'provider.connection.check',
        workspaceId: (int) $tenant->workspace_id,
        tenant: $tenant,
        initiator: $user,
        authorityMode: ExecutionAuthorityMode::ActorBound,
        requiredCapability: 'providers.view',
        providerConnectionId: 123,
        targetScope: [
            'workspace_id' => (int) $tenant->workspace_id,
            'managed_environment_id' => (int) $tenant->getKey(),
            'provider_connection_id' => 123,
        ],
    );

    $decision = QueuedExecutionLegitimacyDecision::deny(
        context: $context,
        checks: [
            'workspace_scope' => 'passed',
            'tenant_scope' => 'failed',
            'capability' => 'not_applicable',
            'tenant_operability' => 'not_applicable',
            'execution_prerequisites' => 'not_applicable',
        ],
        reasonCode: ExecutionDenialReasonCode::InitiatorNotEntitled,
    );

    app(OperationRunService::class)->finalizeExecutionLegitimacyBlockedRun($run, $decision);

    $run->refresh();

    $audit = AuditLog::query()
        ->where('operation_run_id', (int) $run->getKey())
        ->latest('id')
        ->first();

    $report = data_get($run->context, 'verification_report');

    expect($audit)->not->toBeNull()
        ->and($audit?->action)->toBe('operation.blocked')
        ->and($audit?->status)->toBe('blocked')
        ->and($audit?->summary)->toContain('blocked')
        ->and(data_get($audit?->metadata, 'operation_type'))->toBe('provider.connection.check')
        ->and(data_get($audit?->metadata, 'failure_summary.0.reason_code'))->toBe('initiator_not_entitled')
        ->and(data_get($audit?->metadata, 'target_scope.provider_connection_id'))->toBe(123)
        ->and(data_get($audit?->metadata, 'denial_class'))->toBe('initiator_invalid')
        ->and(data_get($audit?->metadata, 'authority_mode'))->toBe('actor_bound')
        ->and(data_get($audit?->metadata, 'acting_identity_type'))->toBe('user')
        ->and($run->summary_counts)->toBe(['total' => 4])
        ->and($report)->toBeArray()
        ->and(VerificationReportSchema::isValidReport($report))->toBeTrue()
        ->and(data_get($report, 'checks.0.key'))->toBe('provider.connection.check')
        ->and(data_get($report, 'summary.overall'))->toBe('blocked')
        ->and(data_get($report, 'checks.0.message'))->toBe(ExecutionDenialReasonCode::InitiatorNotEntitled->message());
});
