<?php

declare(strict_types=1);

use App\Filament\Clusters\Monitoring\AlertsCluster;
use App\Filament\Pages\TenantDashboard;
use App\Filament\Resources\AlertDestinationResource;
use App\Filament\Resources\AlertRuleResource;
use App\Filament\Resources\RestoreRunResource;
use App\Models\AuditLog;
use App\Models\OperationRun;
use App\Models\Tenant;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\Bus;

it('renders operate hub pages DB-only with no outbound HTTP and no queued jobs', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $run = OperationRun::factory()->create([
        'tenant_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'provider.connection.check',
        'status' => 'completed',
        'outcome' => 'blocked',
        'initiator_name' => 'System',
    ]);

    $this->actingAs($user);

    Bus::fake();
    Filament::setTenant(null, true);

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

    assertNoOutboundHttp(function () use ($run, $session): void {
        $this->withSession($session)
            ->get(route('admin.operations.index'))
            ->assertOk()
            ->assertSee('All tenants')
            ->assertDontSee('Scope: Tenant')
            ->assertDontSee('Scope: Workspace');

        $this->withSession($session)
            ->get(route('admin.operations.view', ['run' => (int) $run->getKey()]))
            ->assertOk()
            ->assertSee('All tenants')
            ->assertDontSee('Scope: Tenant')
            ->assertDontSee('Scope: Workspace');

        $this->withSession($session)
            ->followingRedirects()
            ->get(AlertsCluster::getUrl(panel: 'admin'))
            ->assertOk()
            ->assertSee('All tenants')
            ->assertDontSee('Scope: Tenant')
            ->assertDontSee('Scope: Workspace');

        $this->withSession($session)
            ->get(route('admin.monitoring.audit-log'))
            ->assertOk()
            ->assertSee('All tenants')
            ->assertDontSee('Scope: Tenant')
            ->assertDontSee('Scope: Workspace');
    });

    Bus::assertNothingDispatched();
})->group('ops-ux');

it('shows back to tenant on run detail when tenant context is active and entitled', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $run = OperationRun::factory()->create([
        'tenant_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'policy.sync',
        'status' => 'queued',
        'outcome' => 'pending',
    ]);

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

    $response = $this->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ])->get(route('admin.operations.view', ['run' => (int) $run->getKey()]));

    $response
        ->assertOk()
        ->assertSee('← Back to '.$tenant->name)
        ->assertSee(TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant), false)
        ->assertDontSee('Back to Operations');

    $this->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ])->followingRedirects()
        ->get(AlertsCluster::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertDontSee('Back to Operations');

    expect(substr_count((string) $response->getContent(), '← Back to '.$tenant->name))->toBe(1);
})->group('ops-ux');

it('shows back to tenant when filament tenant is absent but last tenant memory exists', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $run = OperationRun::factory()->create([
        'tenant_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'policy.sync',
        'status' => 'queued',
        'outcome' => 'pending',
    ]);

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

    $workspaceId = (int) $tenant->workspace_id;
    $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()];

    $response = $this->withSession([
        WorkspaceContext::SESSION_KEY => $workspaceId,
        WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => $lastTenantMap,
    ])->get(route('admin.operations.view', ['run' => (int) $run->getKey()]));

    $response
        ->assertOk()
        ->assertSee('← Back to '.$tenant->name)
        ->assertSee(TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant), false)
        ->assertSee('Show all operations')
        ->assertDontSee('Back to Operations');
})->group('ops-ux');

it('shows no tenant return affordance when active and last tenant contexts are not entitled', function (): void {
    [$user, $entitledTenant] = createUserWithTenant(role: 'owner');

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

    $run = OperationRun::factory()->create([
        'tenant_id' => (int) $entitledTenant->getKey(),
        'workspace_id' => (int) $entitledTenant->workspace_id,
        'type' => 'policy.sync',
        'status' => 'queued',
        'outcome' => 'pending',
    ]);

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

    $workspaceId = (int) $entitledTenant->workspace_id;

    $response = $this->withSession([
        WorkspaceContext::SESSION_KEY => $workspaceId,
        WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [(string) $workspaceId => (int) $nonEntitledTenant->getKey()],
    ])->get(route('admin.operations.view', ['run' => (int) $run->getKey()]));

    $response
        ->assertOk()
        ->assertSee('Back to Operations')
        ->assertDontSee('← Back to '.$nonEntitledTenant->name)
        ->assertDontSee('Show all operations');
})->group('ops-ux');

it('returns 404 for non-member workspace access on /admin/operations', function (): void {
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();

    // User is NOT a member — stale workspace context is denied as not found.
    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
        ->get(route('admin.operations.index'))
        ->assertNotFound();
})->group('ops-ux');

it('returns 404 for non-entitled tenant dashboard direct access', function (): void {
    $tenant = Tenant::factory()->create();
    $user = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'role' => 'owner',
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant))
        ->assertNotFound();
})->group('ops-ux');

it('keeps member-without-capability workflow start denial as 403 with no run side effects', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'operator');

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

    $this->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(RestoreRunResource::getUrl('create', tenant: $tenant))
        ->assertForbidden();

    expect(OperationRun::query()
        ->where('tenant_id', (int) $tenant->getKey())
        ->exists())->toBeFalse();
})->group('ops-ux');

it('does not mutate workspace or last-tenant session memory on /admin/operations', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

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

    $workspaceId = (int) $tenant->workspace_id;
    $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()];

    $response = $this->withSession([
        WorkspaceContext::SESSION_KEY => $workspaceId,
        WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => $lastTenantMap,
    ])->get(route('admin.operations.index'));

    $response->assertOk();
    $response->assertSessionHas(WorkspaceContext::SESSION_KEY, $workspaceId);
    $response->assertSessionHas(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, $lastTenantMap);
})->group('ops-ux');

it('shows tenant filter label when tenant context is active', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

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

    $this->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ])->get(route('admin.operations.index'))
        ->assertOk()
        ->assertSee('Filtered by tenant: '.$tenant->name)
        ->assertDontSee('Scope: Tenant')
        ->assertDontSee('Scope: Workspace')
        ->assertDontSee('All tenants');
})->group('ops-ux');

it('does not create audit entries when viewing operate hub pages', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $run = OperationRun::factory()->create([
        'tenant_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'policy.sync',
        'status' => 'queued',
        'outcome' => 'pending',
    ]);

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

    $before = (int) AuditLog::query()->count();

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

    $this->withSession($session)
        ->get(route('admin.operations.index'))
        ->assertOk();

    $this->withSession($session)
        ->get(route('admin.operations.view', ['run' => (int) $run->getKey()]))
        ->assertOk();

    $this->withSession($session)
        ->followingRedirects()
        ->get(AlertsCluster::getUrl(panel: 'admin'))
        ->assertOk();

    $this->withSession($session)
        ->get(route('admin.monitoring.audit-log'))
        ->assertOk();

    expect((int) AuditLog::query()->count())->toBe($before);
})->group('ops-ux');

it('suppresses tenant indicator on alert rules list page (manage page)', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

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

    $this->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ])->get(AlertRuleResource::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertDontSee('Filtered by tenant')
        ->assertDontSee('Scope: Tenant')
        ->assertDontSee('Scope: Workspace');
})->group('ops-ux');

it('suppresses tenant indicator on alert destinations list page (manage page)', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

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

    $this->withSession([
        WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
    ])->get(AlertDestinationResource::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertDontSee('Filtered by tenant')
        ->assertDontSee('Scope: Tenant')
        ->assertDontSee('Scope: Workspace');
})->group('ops-ux');

it('suppresses tenant indicator on alert rules list with lastTenantId fallback', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

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

    $workspaceId = (int) $tenant->workspace_id;
    $lastTenantMap = [(string) $workspaceId => (int) $tenant->getKey()];

    $this->withSession([
        WorkspaceContext::SESSION_KEY => $workspaceId,
        WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => $lastTenantMap,
    ])->get(AlertRuleResource::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertDontSee('Filtered by tenant')
        ->assertDontSee('Scope: Tenant');
})->group('ops-ux');
