<?php

declare(strict_types=1);

use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\ReviewPackResource\Pages\ListReviewPacks;
use App\Filament\Resources\ReviewPackResource\Pages\ViewReviewPack;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\OperationRun;
use App\Models\ReviewPack;
use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use App\Services\Evidence\EvidenceSnapshotService;
use App\Services\ReviewPackService;
use App\Services\Settings\SettingsWriter;
use App\Support\Auth\UiTooltips;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\OperationRunType;
use App\Support\OperationRunLinks;
use App\Support\ReviewPackStatus;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Livewire\Features\SupportTesting\Testable;
use Tests\Feature\Concerns\BuildsGovernanceArtifactTruthFixtures;

uses(RefreshDatabase::class, BuildsGovernanceArtifactTruthFixtures::class);

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

function getReviewPackEmptyStateAction(Testable $component, string $name): ?Action
{
    foreach ($component->instance()->getTable()->getEmptyStateActions() as $action) {
        if ($action instanceof Action && $action->getName() === $name) {
            return $action;
        }
    }

    return null;
}

function getReviewPackHeaderAction(Testable $component, string $name): ?Action
{
    $instance = $component->instance();
    $instance->cacheInteractsWithHeaderActions();

    foreach ($instance->getCachedHeaderActions() as $action) {
        if ($action instanceof Action && $action->getName() === $name) {
            return $action;
        }
    }

    return null;
}

function seedReviewPackEvidence(ManagedEnvironment $tenant): EvidenceSnapshot
{
    StoredReport::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'report_type' => StoredReport::REPORT_TYPE_PERMISSION_POSTURE,
        'payload' => [
            'required_count' => 1,
            'granted_count' => 1,
            'permissions' => [
                ['key' => 'DeviceManagementConfiguration.ReadWrite.All', 'status' => 'granted'],
            ],
        ],
    ]);

    StoredReport::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'report_type' => StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES,
        'payload' => [
            'roles' => [
                ['displayName' => 'Global Administrator'],
            ],
        ],
    ]);

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
    ]);

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'finding_type' => Finding::FINDING_TYPE_DRIFT,
    ]);

    OperationRun::factory()->forTenant($tenant)->create([
        'type' => OperationRunType::PolicySync->value,
    ]);

    /** @var EvidenceSnapshotService $service */
    $service = app(EvidenceSnapshotService::class);
    $payload = $service->buildSnapshotPayload($tenant);

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

    foreach ($payload['items'] as $item) {
        $snapshot->items()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'workspace_id' => (int) $tenant->workspace_id,
            'dimension_key' => $item['dimension_key'],
            'state' => $item['state'],
            'required' => $item['required'],
            'source_kind' => $item['source_kind'],
            'source_record_type' => $item['source_record_type'],
            'source_record_id' => $item['source_record_id'],
            'source_fingerprint' => $item['source_fingerprint'],
            'measured_at' => $item['measured_at'],
            'freshness_at' => $item['freshness_at'],
            'summary_payload' => $item['summary_payload'],
            'sort_order' => $item['sort_order'],
        ]);
    }

    return $snapshot->load('items');
}

// ─── List Page ───────────────────────────────────────────────

it('renders the list page for an authorized user', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('index', tenant: $tenant, panel: 'admin'))
        ->assertOk();
});

it('shows review packs belonging to the active tenant', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $otherTenant = ManagedEnvironment::factory()->create();

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $otherTenant->getKey(),
    ]);

    setAdminEnvironmentContext($tenant);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertCanSeeTableRecords([$pack]);
});

it('displays the empty state when no packs exist', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertSee('No review packs yet');
});

// ─── List Page Start CTA Placement ───────────────────────────

it('shows generate only in the empty state when no review packs exist', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $component = Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertTableEmptyStateActionsExistInOrder(['generate_first']);

    $emptyStateAction = getReviewPackEmptyStateAction($component, 'generate_first');
    $headerAction = getReviewPackHeaderAction($component, 'generate_pack');

    expect($emptyStateAction)->not->toBeNull()
        ->and($emptyStateAction?->getLabel())->toBe('Generate first pack')
        ->and($headerAction)->not->toBeNull()
        ->and($headerAction?->isVisible())->toBeFalse();
});

it('shows generate in the header once review packs exist', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertActionVisible('generate_pack');
});

it('disables the generate_first action for a readonly user in the empty state', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly');

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $component = Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertTableEmptyStateActionsExistInOrder(['generate_first']);

    $emptyStateAction = getReviewPackEmptyStateAction($component, 'generate_first');

    expect($emptyStateAction)->not->toBeNull()
        ->and($emptyStateAction?->isDisabled())->toBeTrue()
        ->and($emptyStateAction?->getTooltip())->toBe(UiTooltips::insufficientPermission());
});

it('disables review pack generation actions when the workspace entitlement blocks them', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    app(SettingsWriter::class)->updateWorkspaceSetting(
        actor: $user,
        workspace: $tenant->workspace,
        domain: 'entitlements',
        key: 'review_pack_generation_override_value',
        value: false,
    );

    app(SettingsWriter::class)->updateWorkspaceSetting(
        actor: $user,
        workspace: $tenant->workspace,
        domain: 'entitlements',
        key: 'review_pack_generation_override_reason',
        value: 'Workspace is temporarily limited to manual reporting only',
    );

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    expect(ReviewPackResource::reviewPackGenerationActionTooltip($tenant))
        ->toBe('Review pack generation is disabled by workspace override. Reason: Workspace is temporarily limited to manual reporting only');

    $listPage = Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertTableEmptyStateActionsExistInOrder(['generate_first']);

    $emptyStateAction = getReviewPackEmptyStateAction($listPage, 'generate_first');
    $headerAction = getReviewPackHeaderAction($listPage, 'generate_pack');

    expect($emptyStateAction)->not->toBeNull()
        ->and($emptyStateAction?->isDisabled())->toBeTrue()
        ->and($headerAction)->not->toBeNull()
        ->and($headerAction?->isVisible())->toBeFalse();

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    Livewire::actingAs($user)
        ->test(ViewReviewPack::class, ['record' => $pack->getKey()])
        ->assertActionVisible('regenerate')
        ->assertActionDisabled('regenerate');
});

it('reuses an existing ready pack instead of starting a new run', function (): void {
    Queue::fake();

    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedReviewPackEvidence($tenant);

    $fingerprint = app(ReviewPackService::class)->computeFingerprint($tenant, [
        'include_pii' => true,
        'include_operations' => true,
    ]);

    ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
        'fingerprint' => $fingerprint,
        'expires_at' => now()->addDay(),
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $operationRunsBefore = OperationRun::query()->count();
    $reviewPacksBefore = ReviewPack::query()->count();

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->callAction('generate_pack', [
            'include_pii' => true,
            'include_operations' => true,
        ])
        ->assertNotified();

    expect(OperationRun::query()->count())->toBe($operationRunsBefore);
    expect(ReviewPack::query()->count())->toBe($reviewPacksBefore);

    Queue::assertNothingPushed();
});

it('does not queue generation when no eligible evidence snapshot exists', function (): void {
    Queue::fake();

    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    ReviewPack::factory()->failed()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->callAction('generate_pack', [
            'include_pii' => true,
            'include_operations' => true,
        ])
        ->assertNotified();

    expect(ReviewPack::query()->count())->toBe(1);
    Queue::assertNothingPushed();
});

// ─── Table Row Actions ───────────────────────────────────────

it('shows the download action for a ready pack', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $filePath = 'review-packs/test.zip';
    Storage::disk('exports')->put($filePath, 'PK-fake');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
        'file_path' => $filePath,
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertTableActionVisible('download', $pack);
});

it('keeps expire grouped under More while still allowing owners to expire a ready pack', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $filePath = 'review-packs/expire-test.zip';
    Storage::disk('exports')->put($filePath, 'PK-fake');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
        'file_path' => $filePath,
        'file_disk' => 'exports',
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $livewire = Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertCanSeeTableRecords([$pack]);

    $table = $livewire->instance()->getTable();
    $rowActions = $table->getActions();
    $primaryRowActionNames = collect($rowActions)
        ->reject(static fn ($action): bool => $action instanceof ActionGroup)
        ->map(static fn ($action): ?string => $action->getName())
        ->filter()
        ->values()
        ->all();
    $moreGroup = collect($rowActions)->first(static fn ($action): bool => $action instanceof ActionGroup);
    $moreActionNames = collect($moreGroup?->getActions())
        ->map(static fn ($action): ?string => $action->getName())
        ->filter()
        ->values()
        ->all();

    expect($primaryRowActionNames)->toBe(['download'])
        ->and($moreGroup)->toBeInstanceOf(ActionGroup::class)
        ->and($moreGroup?->getLabel())->toBe('More')
        ->and($moreActionNames)->toEqualCanonicalizing(['expire']);

    $livewire
        ->assertTableActionVisible('expire', $pack)
        ->callTableAction('expire', $pack);

    $pack->refresh();
    expect($pack->status)->toBe(ReviewPackStatus::Expired->value);
    Storage::disk('exports')->assertMissing($filePath);
});

// ─── View Page ───────────────────────────────────────────────

it('renders the view page for a ready pack', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedReviewPackEvidence($tenant);
    $run = OperationRun::factory()->forTenant($tenant)->create([
        'type' => 'environment.review_pack.generate',
    ]);

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
        'operation_run_id' => (int) $run->getKey(),
        'summary' => [
            'finding_count' => 5,
            'report_count' => 2,
            'operation_count' => 12,
            'data_freshness' => [
                'permission_posture' => now()->toIso8601String(),
                'entra_admin_roles' => now()->toIso8601String(),
                'findings' => now()->toIso8601String(),
                'hardening' => now()->toIso8601String(),
            ],
            'evidence_resolution' => [
                'outcome' => 'resolved',
                'snapshot_id' => (int) $snapshot->getKey(),
                'snapshot_fingerprint' => (string) $snapshot->fingerprint,
            ],
        ],
        'options' => ['include_pii' => true, 'include_operations' => true],
    ]);

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin'))
        ->assertOk()
        ->assertSee('Outcome summary')
        ->assertDontSee('Artifact truth')
        ->assertSee('Artifact reference')
        ->assertSee('Review pack #'.$pack->getKey())
        ->assertSee('Lifecycle')
        ->assertSee('Current')
        ->assertSee('Retention')
        ->assertSee('Retained')
        ->assertSee('Publishable')
        ->assertSee('#'.$snapshot->getKey())
        ->assertSee(OperationRunLinks::view($run, $tenant), false)
        ->assertSee('resolved');
});

it('shows blocked publication truth when the source review is no longer publishable', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
    $snapshot = seedReviewPackEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);

    $review->update([
        'status' => 'draft',
        'summary' => array_replace_recursive(is_array($review->summary) ? $review->summary : [], [
            'publish_blockers' => ['Review the missing approval note before publication.'],
        ]),
    ]);

    $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(),
        'summary' => [
            'review_status' => 'draft',
            'review_completeness_state' => 'complete',
            'evidence_resolution' => [
                'outcome' => 'resolved',
                'snapshot_id' => (int) $snapshot->getKey(),
                'snapshot_fingerprint' => (string) $snapshot->fingerprint,
            ],
        ],
    ]);

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin'))
        ->assertOk()
        ->assertSee('Publication blocked')
        ->assertSee('Open the source review before sharing this pack');
});

it('shows internal-only caveats for packs generated from stale source evidence before download', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $snapshot = seedStaleEnvironmentReviewEvidence($tenant);
    $review = $this->makeArtifactTruthReview(
        tenant: $tenant,
        user: $user,
        snapshot: $snapshot,
        reviewOverrides: [
            'status' => 'published',
            'published_at' => now(),
            'published_by_user_id' => (int) $user->getKey(),
            'completeness_state' => 'complete',
        ],
        summaryOverrides: [
            'publish_blockers' => [],
            'section_state_counts' => [
                'complete' => 6,
                'partial' => 0,
                'missing' => 0,
                'stale' => 0,
            ],
        ],
    );

    $pack = $this->makeArtifactTruthReviewPack(
        tenant: $tenant,
        user: $user,
        snapshot: $snapshot,
        review: $review,
        summaryOverrides: [
            'review_status' => 'published',
            'review_completeness_state' => 'complete',
        ],
    );

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListReviewPacks::class)
        ->assertTableActionVisible('download', $pack)
        ->assertSee('Internal only')
        ->assertSee('Refresh the source review before sharing this pack');

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant))
        ->assertOk()
        ->assertSee('Internal only')
        ->assertSee('Download')
        ->assertSee('Refresh the source review before sharing this pack');
});

it('keeps packs from partial evidence internal only instead of publishable', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $snapshot = seedPartialEnvironmentReviewEvidence($tenant);
    $review = $this->makeArtifactTruthReview(
        tenant: $tenant,
        user: $user,
        snapshot: $snapshot,
        reviewOverrides: [
            'status' => 'ready',
            'completeness_state' => 'complete',
        ],
        summaryOverrides: [
            'publish_blockers' => [],
            'section_state_counts' => [
                'complete' => 6,
                'partial' => 0,
                'missing' => 0,
                'stale' => 0,
            ],
        ],
    );

    $pack = $this->makeArtifactTruthReviewPack(
        tenant: $tenant,
        user: $user,
        snapshot: $snapshot,
        review: $review,
        summaryOverrides: [
            'review_status' => 'ready',
            'review_completeness_state' => 'complete',
        ],
    );

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin'))
        ->assertOk()
        ->assertSee('Internal only')
        ->assertSee('Complete the source review before sharing this pack')
        ->assertDontSee('Publishable');
});

it('shows download header action on view page for a ready pack', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ViewReviewPack::class, ['record' => $pack->getKey()])
        ->assertActionVisible('download');
});

it('shows regenerate header action on view page', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ViewReviewPack::class, ['record' => $pack->getKey()])
        ->assertActionVisible('regenerate');
});

it('hides regenerate and raw pack diagnostics in the customer review pack flow', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'readonly');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'initiated_by_user_id' => (int) $user->getKey(),
        'sha256' => hash('sha256', 'customer-pack-flow'),
        'fingerprint' => hash('sha256', 'customer-pack-fingerprint'),
    ]);

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin').'?'.http_build_query([
            'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
        ]))
        ->assertOk()
        ->assertSee('Outcome summary')
        ->assertDontSee('Regenerate')
        ->assertDontSee('SHA-256')
        ->assertDontSee('Fingerprint')
        ->assertDontSee('Include PII')
        ->assertDontSee('Include operations');

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::withQueryParams(['source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE])
        ->actingAs($user)
        ->test(ViewReviewPack::class, ['record' => $pack->getKey()])
        ->assertActionVisible('download')
        ->assertActionDoesNotExist('regenerate');
});

// ─── Non-Member Access ───────────────────────────────────────

it('returns 404 for non-members on list page', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $otherTenant = ManagedEnvironment::factory()->create();

    [$user] = createUserWithTenant($otherTenant, role: 'owner');

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('index', tenant: $tenant, panel: 'admin'))
        ->assertNotFound();
});

it('returns 404 for non-members on view page', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $otherTenant = ManagedEnvironment::factory()->create();

    [$user] = createUserWithTenant($otherTenant, role: 'owner');

    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
    ]);

    $this->actingAs($user)
        ->get(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant))
        ->assertNotFound();
});
