<?php

declare(strict_types=1);

use App\Filament\Pages\BaselineCompareLanding;
use App\Models\ManagedEnvironment;
use App\Support\EnvironmentDashboard\EnvironmentDashboardSummaryBuilder;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Support\Arr;

function baselineCompareRouteContractForbiddenQueryKeys(): array
{
    return [
        'environment_id',
        'tenant',
        'tenant_id',
        'managed_environment_id',
        'environment',
        'tenant_scope',
        'tableFilters',
    ];
}

it('generates a canonical environment-owned baseline compare URL without legacy scope query keys', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user);

    $url = ManagedEnvironmentLinks::baselineCompareUrl($tenant, [
        'environment_id' => (int) $tenant->getKey(),
        'tenant' => (string) $tenant->external_id,
        'tenant_id' => (int) $tenant->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'environment' => 'legacy-query-value',
        'tenant_scope' => 'selected',
        'tableFilters' => ['managed_environment_id' => ['value' => (int) $tenant->getKey()]],
        'baseline_profile_id' => 42,
        'subject_key' => 'wifi-corp-profile',
    ]);

    parse_str((string) parse_url($url, PHP_URL_QUERY), $query);

    expect((string) parse_url($url, PHP_URL_PATH))
        ->toBe(sprintf(
            '/admin/workspaces/%s/environments/%s/baseline-compare',
            $tenant->workspace()->firstOrFail()->slug,
            $tenant->getRouteKey(),
        ))
        ->and(array_keys($query))->not->toContain(...baselineCompareRouteContractForbiddenQueryKeys())
        ->and($query)->toMatchArray([
            'baseline_profile_id' => '42',
            'subject_key' => 'wifi-corp-profile',
        ]);
});

it('renders baseline compare from the route-owned environment context', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(ManagedEnvironmentLinks::baselineCompareUrl($tenant))
        ->assertOk()
        ->assertSeeText('Baseline Compare')
        ->assertSeeText($tenant->workspace()->firstOrFail()->name)
        ->assertSeeText($tenant->name)
        ->assertSeeText('This environment has no baseline assignment');
});

it('rejects old workspace-style baseline compare URLs and remembered environment fallback', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    Filament::setTenant(null, true);

    $this->actingAs($user)
        ->withSession([
            WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
            WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
                (string) $tenant->workspace_id => (int) $tenant->getKey(),
            ],
        ])
        ->get('/admin/baseline-compare-landing?environment_id='.(int) $tenant->getKey())
        ->assertNotFound();

    expect(BaselineCompareLanding::canAccess())->toBeFalse();
});

it('rejects baseline compare when the workspace route and environment route disagree', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    $foreignTenant = ManagedEnvironment::factory()->active()->create(['name' => 'Foreign Environment']);
    createUserWithTenant(tenant: $foreignTenant, user: $user, role: 'owner');

    $url = sprintf(
        '/admin/workspaces/%s/environments/%s/baseline-compare',
        $tenant->workspace()->firstOrFail()->slug,
        $foreignTenant->getRouteKey(),
    );

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get($url)
        ->assertNotFound();
});

it('emits the environment-owned route from the environment dashboard baseline compare action', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $summary = app(EnvironmentDashboardSummaryBuilder::class)
        ->build($tenant, $user)
        ->toArray();

    $baselineCompareStatus = Arr::first(
        $summary['governanceStatus'],
        static fn (array $status): bool => ($status['key'] ?? null) === 'baseline_compare',
    );

    $url = is_array($baselineCompareStatus) ? ($baselineCompareStatus['actionUrl'] ?? null) : null;
    parse_str((string) parse_url((string) $url, PHP_URL_QUERY), $query);

    expect($url)->toBe(ManagedEnvironmentLinks::baselineCompareUrl($tenant))
        ->and((string) parse_url((string) $url, PHP_URL_PATH))->toEndWith('/environments/'.$tenant->getRouteKey().'/baseline-compare')
        ->and(array_keys($query))->not->toContain(...baselineCompareRouteContractForbiddenQueryKeys());
});
