<?php

declare(strict_types=1);

use App\Filament\Resources\BaselineProfileResource;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment;
use App\Models\ManagedEnvironment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;

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

uses(RefreshDatabase::class);

function spec202SmokeLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect = ''): string
{
    return route('admin.local.smoke-login', array_filter([
        'email' => $user->email,
        'tenant' => $tenant->external_id,
        'workspace' => $tenant->workspace->slug,
        'redirect' => $redirect,
    ], static fn (?string $value): bool => filled($value)));
}

it('smokes governance subject scope create, edit, and view surfaces', function (): void {
    [$user, $tenant] = createUserWithTenant(
        role: 'owner',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

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

    DB::table('baseline_profiles')
        ->where('id', (int) $legacyProfile->getKey())
        ->update([
            'scope_jsonb' => json_encode([
                'policy_types' => ['deviceConfiguration'],
                'foundation_types' => ['assignmentFilter'],
            ], JSON_THROW_ON_ERROR),
            'updated_at' => now(),
        ]);

    $captureProfile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Spec202 Capture Browser Baseline',
        'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []],
    ]);

    $compareProfile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'name' => 'Spec202 Compare Browser Baseline',
        'scope_jsonb' => ['policy_types' => ['deviceConfiguration'], 'foundation_types' => []],
    ]);

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

    $compareProfile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);

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

    visit(spec202SmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit(BaselineProfileResource::getUrl('create', panel: 'admin'))
        ->waitForText('Governed subject summary')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Support readiness')
        ->assertSee('Selection feedback');

    visit(BaselineProfileResource::getUrl('edit', ['record' => $legacyProfile], panel: 'admin'))
        ->waitForText('Governed subject summary')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Support readiness')
        ->assertSee('Device Configuration')
        ->assertSee('Assignment Filter')
        ->assertSee('This Intune-first selection will be saved forward as canonical governed-subject scope V2.');

    visit(BaselineProfileResource::getUrl('view', ['record' => $captureProfile], panel: 'admin'))
        ->waitForText('Governed subject summary')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Support readiness')
        ->assertSee('Capture baseline')
        ->click('Capture baseline')
        ->waitForText('Source environment')
        ->click('Cancel')
        ->assertSee('Capture baseline');

    visit(BaselineProfileResource::getUrl('view', ['record' => $compareProfile], panel: 'admin'))
        ->waitForText('Governed subject summary')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Support readiness')
        ->assertSee('Normalization lineage')
        ->assertSee('Canonical governed-subject scope V2 is already stored for this baseline profile.')
        ->assertSee('Compare now')
        ->click('Compare now')
        ->waitForText('Target environment')
        ->click('Cancel')
        ->assertSee('Compare now');
});

it('smokes tolerant invalid scope rendering on the baseline detail surface', function (): void {
    [$user, $tenant] = createUserWithTenant(
        role: 'owner',
        workspaceRole: 'manager',
        ensureDefaultMicrosoftProviderConnection: false,
    );

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

    DB::table('baseline_profiles')
        ->where('id', (int) $invalidProfile->getKey())
        ->update([
            'scope_jsonb' => json_encode([
                'version' => 2,
                'entries' => [
                    [
                        'domain_key' => 'platform_foundation',
                        'subject_class' => 'configuration_resource',
                        'subject_type_keys' => ['intuneRoleAssignment'],
                        'filters' => [],
                    ],
                ],
            ], JSON_THROW_ON_ERROR),
            'updated_at' => now(),
        ]);

    visit(spec202SmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit(BaselineProfileResource::getUrl('view', ['record' => $invalidProfile], panel: 'admin'))
        ->waitForText('Governed subject summary')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertSee('Invalid governed subject selection.')
        ->assertSee('Support readiness')
        ->assertSee('Capture: blocked. Compare: blocked.')
        ->assertSee('Stored scope is invalid and must be repaired before capture or compare can continue.');
});
