<?php

declare(strict_types=1);

use App\Models\Tenant;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\Request;

uses(RefreshDatabase::class);

function canonicalAdminTenantRequest(): Request
{
    $request = Request::create('/admin');
    $request->setLaravelSession(app('session.store'));

    return $request;
}

it('clears tenant-sensitive persisted filters when the canonical admin tenant changes', function (): void {
    $tenantA = Tenant::factory()->create();
    [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner');

    $tenantB = Tenant::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
    ]);

    createUserWithTenant(tenant: $tenantB, user: $user, role: 'owner');

    $this->actingAs($user);
    Filament::setTenant(null, true);

    $workspaceId = (int) $tenantA->workspace_id;
    $filtersSessionKey = 'filament.test.filters';

    session()->put(WorkspaceContext::SESSION_KEY, $workspaceId);
    session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
        (string) $workspaceId => (int) $tenantA->getKey(),
    ]);
    session()->put($filtersSessionKey, [
        'run_ids' => ['baseline_operation_run_id' => 101],
        'status' => ['value' => 'new'],
    ]);

    app(CanonicalAdminTenantFilterState::class)->sync(
        $filtersSessionKey,
        ['run_ids'],
        canonicalAdminTenantRequest(),
        null,
    );

    session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
        (string) $workspaceId => (int) $tenantB->getKey(),
    ]);

    app(CanonicalAdminTenantFilterState::class)->sync(
        $filtersSessionKey,
        ['run_ids'],
        canonicalAdminTenantRequest(),
        null,
    );

    expect(session()->get($filtersSessionKey))
        ->toMatchArray([
            'status' => ['value' => 'new'],
        ])
        ->not->toHaveKey('run_ids');
});

it('can seed a non-default tenant filter with the canonical tenant external id', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user);
    Filament::setTenant(null, true);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
    session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
        (string) $tenant->workspace_id => (int) $tenant->getKey(),
    ]);

    app(CanonicalAdminTenantFilterState::class)->sync(
        'filament.provider.filters',
        request: canonicalAdminTenantRequest(),
        tenantFilterName: 'tenant',
        tenantAttribute: 'external_id',
    );

    expect(session()->get('filament.provider.filters'))
        ->toMatchArray([
            'tenant' => ['value' => (string) $tenant->external_id],
        ]);
});

it('preserves existing non-tenant filters when canonical tenant state seeds a tenant filter', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user);
    Filament::setTenant(null, true);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
    session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
        (string) $tenant->workspace_id => (int) $tenant->getKey(),
    ]);
    session()->put('filament.provider.filters', [
        'status' => ['value' => 'active'],
    ]);

    app(CanonicalAdminTenantFilterState::class)->sync(
        'filament.provider.filters',
        request: canonicalAdminTenantRequest(),
        tenantFilterName: 'tenant',
        tenantAttribute: 'external_id',
    );

    expect(session()->get('filament.provider.filters'))
        ->toMatchArray([
            'status' => ['value' => 'active'],
            'tenant' => ['value' => (string) $tenant->external_id],
        ]);
});

it('does not persist an empty filter bag when only canonical tenant state is synced', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user);
    Filament::setTenant(null, true);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
    session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
        (string) $tenant->workspace_id => (int) $tenant->getKey(),
    ]);

    app(CanonicalAdminTenantFilterState::class)->sync(
        'filament.findings.filters',
        request: canonicalAdminTenantRequest(),
        tenantFilterName: null,
    );

    expect(session()->has('filament.findings.filters'))->toBeFalse();
});
