<?php

declare(strict_types=1);

use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Jobs\GenerateReviewPackJob;
use App\Models\AuditLog;
use App\Models\EvidenceSnapshot;
use App\Services\EnvironmentReviews\EnvironmentReviewLifecycleService;
use App\Services\EnvironmentReviews\EnvironmentReviewService;
use App\Services\ReviewPackService;
use App\Support\Audit\AuditActionId;
use Illuminate\Support\Facades\Storage;

beforeEach(function (): void {
    Storage::fake('exports');
});

it('records environment-review audit history across create, refresh, publish, export, successor, and archive flows', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $reviewService = app(EnvironmentReviewService::class);
    $lifecycle = app(EnvironmentReviewLifecycleService::class);

    $initialSnapshot = seedEnvironmentReviewEvidence($tenant);
    $review = $reviewService->create($tenant, $initialSnapshot, $user);
    $review = $reviewService->compose($review);

    EvidenceSnapshot::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('status', 'active')
        ->update([
            'status' => 'expired',
            'expires_at' => now(),
        ]);

    $refreshSnapshot = seedEnvironmentReviewEvidence(
        tenant: $tenant,
        findingCount: 6,
        driftCount: 2,
        operationRunCount: 2,
    );
    $review = $reviewService->refresh($review, $user, $refreshSnapshot);
    $review = $reviewService->compose($review->fresh());

    $published = $lifecycle->publish($review, $user, 'Publishing the current review pack.');

    EvidenceSnapshot::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('status', 'active')
        ->update([
            'status' => 'expired',
            'expires_at' => now(),
        ]);

    $pack = app(ReviewPackService::class)->generateFromReview($published, $user, [
        'include_pii' => true,
        'include_operations' => true,
    ]);

    $job = new GenerateReviewPackJob(
        reviewPackId: (int) $pack->getKey(),
        operationRunId: (int) $pack->operation_run_id,
    );
    app()->call([$job, 'handle']);

    $nextReview = $lifecycle->createNextReview($published->fresh(), $user, seedEnvironmentReviewEvidence(
        tenant: $tenant,
        findingCount: 7,
        driftCount: 1,
        operationRunCount: 3,
    ));

    $lifecycle->archive($nextReview, $user, 'Replacing with a newer governance review.');

    expect(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewCreated->value)->exists())->toBeTrue()
        ->and(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewRefreshed->value)->exists())->toBeTrue()
        ->and(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewPublished->value)->exists())->toBeTrue()
        ->and(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewExported->value)->exists())->toBeTrue()
        ->and(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewSuccessorCreated->value)->exists())->toBeTrue()
        ->and(AuditLog::query()->where('action', AuditActionId::EnvironmentReviewArchived->value)->exists())->toBeTrue();

    $exportAudit = AuditLog::query()
        ->where('action', AuditActionId::EnvironmentReviewExported->value)
        ->latest('id')
        ->first();

    $publishAudit = AuditLog::query()
        ->where('action', AuditActionId::EnvironmentReviewPublished->value)
        ->latest('id')
        ->first();

    $archiveAudit = AuditLog::query()
        ->where('action', AuditActionId::EnvironmentReviewArchived->value)
        ->latest('id')
        ->first();

    expect($exportAudit)->not->toBeNull()
        ->and($exportAudit?->resource_type)->toBe('environment_review')
        ->and(data_get($exportAudit?->metadata, 'review_pack_id'))->toBe((int) $pack->getKey())
        ->and(data_get($publishAudit?->metadata, 'reason'))->toBe('Publishing the current review pack.')
        ->and(data_get($archiveAudit?->metadata, 'reason'))->toBe('Replacing with a newer governance review.');
});

it('records customer workspace interpretation metadata when a environment review is opened', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'readonly');
    $snapshot = seedEnvironmentReviewEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);

    $review->forceFill([
        'status' => 'published',
        'published_at' => now(),
        'published_by_user_id' => (int) $user->getKey(),
    ])->save();

    setAdminEnvironmentContext($tenant);

    $this->actingAs($user)
        ->get(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant).'?'.http_build_query([
            CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1,
            'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
            'tenant_filter_id' => (string) $tenant->getKey(),
            'interpretation_version' => $review->controlInterpretationVersion(),
        ]))
        ->assertOk();

    $audit = AuditLog::query()
        ->where('action', AuditActionId::EnvironmentReviewOpened->value)
        ->latest('id')
        ->first();

    expect($audit)->not->toBeNull()
        ->and($audit?->resource_type)->toBe('environment_review')
        ->and(data_get($audit?->metadata, 'review_id'))->toBe((int) $review->getKey())
        ->and(data_get($audit?->metadata, 'source_surface'))->toBe(CustomerReviewWorkspace::SOURCE_SURFACE)
        ->and(data_get($audit?->metadata, 'tenant_filter_id'))->toBe((string) $tenant->getKey())
        ->and(data_get($audit?->metadata, 'interpretation_version'))->toBe($review->controlInterpretationVersion());
});
