<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Filament\Resources\BackupSetResource;
use App\Filament\Widgets\Dashboard\NeedsAttention;
use App\Filament\Widgets\Dashboard\RecoveryReadiness;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\Finding;
use App\Models\InventoryItem;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Services\Auth\CapabilityResolver;
use App\Support\Auth\Capabilities;
use App\Support\Rbac\UiTooltips;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\Gate;
use Livewire\Livewire;

use function Pest\Laravel\mock;

it('does not leak data across tenants on the dashboard', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    $otherTenant = ManagedEnvironment::factory()->create();

    InventoryItem::factory()->create([
        'managed_environment_id' => $otherTenant->getKey(),
        'external_id' => 'other-tenant-finding',
        'display_name' => 'Other ManagedEnvironment Policy',
    ]);

    Finding::factory()->create([
        'managed_environment_id' => $otherTenant->getKey(),
        'finding_type' => Finding::FINDING_TYPE_DRIFT,
        'subject_external_id' => 'other-tenant-finding',
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => $otherTenant->getKey(),
        'type' => 'inventory_sync',
        'status' => 'running',
        'outcome' => 'pending',
        'initiator_name' => 'System',
    ]);

    $this->actingAs($user);

    $this->get(EnvironmentDashboard::getUrl(tenant: $tenant))
        ->assertOk()
        ->assertDontSee('Other ManagedEnvironment Policy');
});

it('keeps backup summary truth visible on the dashboard while blocked backup drill-through routes still fail with 403', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner', ensureDefaultMicrosoftProviderConnection: false);
    $this->actingAs($user);

    $backupSet = BackupSet::factory()->for($tenant)->create([
        'name' => 'Stale scoped backup',
        'item_count' => 1,
        'completed_at' => now()->subDays(2),
    ]);

    BackupItem::factory()->for($tenant)->for($backupSet)->create([
        'payload' => ['id' => 'policy-stale'],
        'metadata' => [],
        'assignments' => [],
    ]);

    Gate::define(Capabilities::TENANT_VIEW, fn (): bool => false);

    mock(CapabilityResolver::class, function ($mock) use ($tenant): void {
        $mock->shouldReceive('isMember')
            ->andReturnUsing(static fn ($user, ManagedEnvironment $resolvedTenant): bool => (int) $resolvedTenant->getKey() === (int) $tenant->getKey());

        $mock->shouldReceive('primeMemberships')->zeroOrMoreTimes();

        $mock->shouldReceive('can')
            ->andReturnUsing(static function ($user, ManagedEnvironment $resolvedTenant, string $capability) use ($tenant): bool {
                expect((int) $resolvedTenant->getKey())->toBe((int) $tenant->getKey());

                return match ($capability) {
                    Capabilities::TENANT_VIEW => false,
                    default => true,
                };
            });
    });

    setAdminPanelContext($tenant);

    Livewire::test(NeedsAttention::class)
        ->assertSee('Latest backup is stale')
        ->assertSee(UiTooltips::INSUFFICIENT_PERMISSION)
        ->assertSee('Open latest backup');

    Livewire::test(RecoveryReadiness::class)
        ->assertSee('Backup posture')
        ->assertSee('Stale');

    $this->get(EnvironmentDashboard::getUrl(tenant: $tenant))
        ->assertOk();

    $this->get(BackupSetResource::getUrl('index', tenant: $tenant))
        ->assertForbidden();
});
