<?php

declare(strict_types=1);

use App\Filament\Resources\AlertDestinationResource;
use App\Filament\Resources\BackupSetResource;
use App\Filament\Resources\BaselineProfileResource;
use App\Filament\Resources\BaselineSnapshotResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Resources\PolicyVersionResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\Workspaces\WorkspaceResource;
use App\Models\AlertDestination;
use App\Models\BackupSet;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\BaselineSnapshotItem;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\Findings\FindingExceptionService;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\Workspaces\WorkspaceContext;

pest()->browser()->timeout(20_000);

function spec192ApprovedFindingException(ManagedEnvironment $tenant, User $requester)
{
    $approver = User::factory()->create();
    createUserWithTenant(tenant: $tenant, user: $approver, role: 'owner', workspaceRole: 'manager');

    $finding = Finding::factory()->for($tenant)->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_RISK_ACCEPTED,
    ]);

    /** @var FindingExceptionService $service */
    $service = app(FindingExceptionService::class);

    $requested = $service->request($finding, $tenant, $requester, [
        'owner_user_id' => (int) $requester->getKey(),
        'request_reason' => 'Browser smoke test exception request.',
        'review_due_at' => now()->addDays(7)->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
    ]);

    return $service->approve($requested, $approver, [
        'effective_from' => now()->subDay()->toDateTimeString(),
        'expires_at' => now()->addDays(14)->toDateTimeString(),
        'approval_reason' => 'Browser smoke approval.',
    ]);
}

it('smokes remediated standard record pages with contextual navigation and one clear next step', function (): void {
    $tenant = ManagedEnvironment::factory()->active()->create([
        'name' => 'Spec192 Browser ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

    $onboardingTenant = ManagedEnvironment::factory()->onboarding()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Spec192 Browser Onboarding ManagedEnvironment',
    ]);
    createUserWithTenant(
        tenant: $onboardingTenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    createOnboardingDraft([
        'workspace' => $onboardingTenant->workspace,
        'tenant' => $onboardingTenant,
        'started_by' => $user,
        'updated_by' => $user,
        'state' => [
            'entra_tenant_id' => (string) $onboardingTenant->managed_environment_id,
            'environment_name' => (string) $onboardingTenant->name,
        ],
    ]);

    $profile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Spec192 Browser Baseline',
    ]);

    $baselineSnapshot = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $profile->getKey(),
    ]);

    $profile->update(['active_snapshot_id' => (int) $baselineSnapshot->getKey()]);

    \App\Models\BaselineTenantAssignment::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'baseline_profile_id' => (int) $profile->getKey(),
    ]);

    $run = OperationRun::factory()->forTenant($tenant)->create([
        'workspace_id' => (int) $tenant->workspace_id,
    ]);

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

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

    $exception = spec192ApprovedFindingException($tenant, $user);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);

    $this->actingAs($user)->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ]);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    visit(BaselineProfileResource::getUrl('view', ['record' => $profile], panel: 'admin'))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee('Review compare matrix')
        ->assertSee('Compare now');

    visit(EvidenceSnapshotResource::getUrl('view', ['record' => $snapshot], tenant: $tenant, panel: 'admin'))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee('Review pack')
        ->assertSee('Refresh evidence');

    visit(FindingExceptionResource::getUrl('view', ['record' => $exception], tenant: $tenant))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee('Open finding')
        ->assertSee('Renew exception');

    visit(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee('Outcome summary')
        ->assertSee('Evidence snapshot');

    visit(ManagedEnvironmentResource::getUrl('edit', ['record' => $onboardingTenant], panel: 'admin'))
        ->waitForText('Environment governance overview')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee((string) $onboardingTenant->name)
        ->assertSee('Recommended next actions');
});

it('smokes the explicit workflow-heavy tenant detail exception without javascript errors', function (): void {
    $tenant = ManagedEnvironment::factory()->active()->create([
        'name' => 'Spec192 Workflow ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

    $this->actingAs($user)->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ]);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    visit(ManagedEnvironmentResource::getUrl('view', ['record' => $tenant], panel: 'admin'))
        ->waitForText('Environment governance overview')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)
        ->assertSee((string) $tenant->name)
        ->assertSee('Provider Health');
});

it('smokes the compliant reference baseline without header regressions or javascript errors', function (): void {
    $tenant = ManagedEnvironment::factory()->active()->create([
        'name' => 'Spec192 Reference ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);
    $workspace = $tenant->workspace;

    $profile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Spec192 Reference Baseline',
    ]);

    $baselineSnapshot = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $profile->getKey(),
    ]);

    $profile->update(['active_snapshot_id' => (int) $baselineSnapshot->getKey()]);

    $policy = Policy::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'display_name' => 'Spec192 Browser Policy',
    ]);

    $version = PolicyVersion::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'policy_id' => (int) $policy->getKey(),
        'baseline_profile_id' => (int) $profile->getKey(),
        'version_number' => 4,
    ]);

    BaselineSnapshotItem::factory()->create([
        'baseline_snapshot_id' => (int) $baselineSnapshot->getKey(),
        'meta_jsonb' => [
            'display_name' => 'Spec192 Browser Policy',
            'version_reference' => [
                'policy_version_id' => (int) $version->getKey(),
            ],
        ],
    ]);

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'name' => 'Spec192 Browser Backup',
    ]);

    OperationRun::factory()->forTenant($tenant)->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'backup_set.update',
        'context' => [
            'backup_set_id' => (int) $backupSet->getKey(),
        ],
    ]);

    $reviewSnapshot = seedEnvironmentReviewEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $reviewSnapshot);

    $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) $reviewSnapshot->getKey(),
        'initiated_by_user_id' => (int) $user->getKey(),
    ]);

    $destination = AlertDestination::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'name' => 'Spec192 Browser Destination',
    ]);

    $this->actingAs($user)->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ]);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);

    visit(ReviewPackResource::getUrl('view', ['record' => $pack], tenant: $tenant, panel: 'admin'))
        ->waitForText('Download')
        ->assertNoJavaScriptErrors()
        ->assertSee('Regenerate');

    visit(AlertDestinationResource::getUrl('view', ['record' => $destination], panel: 'admin'))
        ->waitForText('Send test message')
        ->assertNoJavaScriptErrors()
        ->assertSee('Details');

    visit(PolicyVersionResource::getUrl('view', ['record' => $version], tenant: $tenant))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertSee('View snapshot');

    visit(WorkspaceResource::getUrl('view', ['record' => $workspace], panel: 'admin'))
        ->waitForText('Memberships')
        ->assertNoJavaScriptErrors()
        ->assertSee('Edit');

    visit(BaselineSnapshotResource::getUrl('view', ['record' => $baselineSnapshot], panel: 'admin'))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length > 0", true)
        ->assertSee('Spec192 Browser Policy');

    visit(BackupSetResource::getUrl('view', ['record' => $backupSet], tenant: $tenant))
        ->waitForText('Related context')
        ->assertNoJavaScriptErrors()
        ->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length > 0", true)
        ->assertSee('Operations');
});
