<?php

declare(strict_types=1);

use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EnvironmentReviewResource\Pages\ViewEnvironmentReview;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Widgets\ManagedEnvironment\ManagedEnvironmentReviewPackCard;
use App\Models\AuditLog;
use App\Models\EvidenceSnapshot;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Support\Audit\AuditActionId;
use App\Support\EnvironmentReviewStatus;
use App\Support\Evidence\EvidenceSnapshotStatus;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;

uses(RefreshDatabase::class);

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

it('renders a customer workspace link from environment review detail context', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedEnvironmentReviewEvidence($tenant);

    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $review->forceFill([
        'status' => EnvironmentReviewStatus::Published->value,
        'published_at' => now(),
        'published_by_user_id' => (int) $user->getKey(),
    ])->save();

    $this->actingAs($user)
        ->get(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant))
        ->assertOk()
        ->assertSee(CustomerReviewWorkspace::environmentFilterUrl($tenant), false);
});

it('adds a customer workspace entry to evidence snapshot related context', function (): void {
    $tenant = ManagedEnvironment::factory()->create();

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

    $entry = collect(EvidenceSnapshotResource::relatedContextEntries($snapshot))
        ->firstWhere('key', 'customer_review_workspace');

    expect($entry)->not->toBeNull()
        ->and($entry['targetUrl'] ?? null)->toBe(CustomerReviewWorkspace::environmentFilterUrl($tenant));
});

it('renders a customer workspace link from review pack detail context', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedEnvironmentReviewEvidence($tenant);

    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $review->forceFill([
        'status' => EnvironmentReviewStatus::Published->value,
        'published_at' => now(),
        'published_by_user_id' => (int) $user->getKey(),
    ])->save();

    Storage::disk('exports')->put('review-packs/customer-workspace-link.zip', 'PK-test');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'environment_review_id' => (int) $review->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
        'initiated_by_user_id' => (int) $user->getKey(),
        'file_path' => 'review-packs/customer-workspace-link.zip',
        'file_disk' => 'exports',
    ]);

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin'))
        ->assertOk()
        ->assertSee(CustomerReviewWorkspace::environmentFilterUrl($tenant), false);
});

it('renders a customer workspace launch button on the environment review pack widget', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedEnvironmentReviewEvidence($tenant);

    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $review->forceFill([
        'status' => EnvironmentReviewStatus::Published->value,
        'published_at' => now(),
        'published_by_user_id' => (int) $user->getKey(),
    ])->save();

    Storage::disk('exports')->put('review-packs/widget-customer-workspace.zip', 'PK-test');

    ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'environment_review_id' => (int) $review->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
        'initiated_by_user_id' => (int) $user->getKey(),
        'file_path' => 'review-packs/widget-customer-workspace.zip',
        'file_disk' => 'exports',
    ]);

    setAdminPanelContext($tenant);

    Livewire::actingAs($user)
        ->test(ManagedEnvironmentReviewPackCard::class, ['record' => $tenant])
        ->assertSee('Customer workspace')
        ->assertSee(CustomerReviewWorkspace::environmentFilterUrl($tenant), false);
});

it('keeps the linked environment review detail read-only for a readonly-capable actor', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly');
    $snapshot = seedEnvironmentReviewEvidence($tenant);

    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $review->forceFill([
        'status' => EnvironmentReviewStatus::Published->value,
        'published_at' => now(),
        'published_by_user_id' => (int) $user->getKey(),
    ])->save();

    Storage::disk('exports')->put('review-packs/customer-workspace-detail-download.zip', 'PK-test');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'environment_review_id' => (int) $review->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
        'initiated_by_user_id' => (int) $user->getKey(),
        'file_path' => 'review-packs/customer-workspace-detail-download.zip',
        'file_disk' => 'exports',
    ]);

    $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save();

    setAdminPanelContext($tenant);

    Livewire::withQueryParams([
        CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1,
        'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
        'tenant_filter_id' => (string) $tenant->getKey(),
        'interpretation_version' => $review->controlInterpretationVersion(),
    ])
        ->actingAs($user)
        ->test(ViewEnvironmentReview::class, ['record' => $review->getKey()])
        ->assertSee('Outcome summary')
        ->assertActionVisible('download_current_review_pack')
        ->assertActionDoesNotExist('publish_review')
        ->assertActionDoesNotExist('refresh_review')
        ->assertActionDoesNotExist('create_next_review')
        ->assertActionDoesNotExist('export_executive_pack')
        ->assertActionDoesNotExist('archive_review');

    $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());
});
