<?php

declare(strict_types=1);

use App\Filament\Resources\BackupSetResource\Pages\EditBackupSet;
use App\Filament\Resources\BackupSetResource\RelationManagers\BackupItemsRelationManager;
use App\Jobs\RemovePoliciesFromBackupSetJob;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\OperationRun;
use Filament\Actions\Action;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

uses(RefreshDatabase::class);

describe('Backup items relation manager UI enforcement', function () {
    it('shows add policies as visible but disabled for readonly members', function (): void {
        [$user, $tenant] = createUserWithTenant(role: 'readonly');

        $this->actingAs($user);
        setAdminPanelContext($tenant);

        $backupSet = BackupSet::factory()->create([
            'managed_environment_id' => $tenant->id,
            'name' => 'Test backup',
        ]);

        $item = BackupItem::factory()->for($backupSet)->for($tenant)->create();

        Livewire::test(BackupItemsRelationManager::class, [
            'ownerRecord' => $backupSet,
            'pageClass' => EditBackupSet::class,
        ])
            ->assertTableActionVisible('addPolicies')
            ->assertTableActionDisabled('addPolicies')
            ->assertTableActionExists('addPolicies', function (Action $action): bool {
                return $action->getTooltip() === 'You do not have permission to add policies.';
            })
            ->assertTableBulkActionVisible('bulk_remove')
            ->assertTableBulkActionDisabled('bulk_remove', [$item]);
    });

    it('shows add policies as enabled for owner members', function (): void {
        [$user, $tenant] = createUserWithTenant(role: 'owner');

        $this->actingAs($user);
        setAdminPanelContext($tenant);

        $backupSet = BackupSet::factory()->create([
            'managed_environment_id' => $tenant->id,
            'name' => 'Test backup',
        ]);

        $item = BackupItem::factory()->for($backupSet)->for($tenant)->create();

        Livewire::test(BackupItemsRelationManager::class, [
            'ownerRecord' => $backupSet,
            'pageClass' => EditBackupSet::class,
        ])
            ->assertTableActionVisible('addPolicies')
            ->assertTableActionEnabled('addPolicies')
            ->assertTableBulkActionVisible('bulk_remove')
            ->assertTableBulkActionEnabled('bulk_remove', [$item]);
    });

    it('hides actions after tenant scope is revoked mid-session', function (): void {
        [$user, $tenant] = createUserWithTenant(role: 'owner');
        $otherTenant = \App\Models\ManagedEnvironment::factory()->active()->create([
            'workspace_id' => (int) $tenant->workspace_id,
            'name' => 'Other managed environment',
        ]);
        createUserWithTenant(tenant: $otherTenant, user: $user, role: 'owner');

        $this->actingAs($user);
        setAdminPanelContext($tenant);

        $backupSet = BackupSet::factory()->create([
            'managed_environment_id' => $tenant->id,
            'name' => 'Test backup',
        ]);

        BackupItem::factory()->for($backupSet)->for($tenant)->create();

        $component = Livewire::test(BackupItemsRelationManager::class, [
            'ownerRecord' => $backupSet,
            'pageClass' => EditBackupSet::class,
        ])
            ->assertTableActionVisible('addPolicies')
            ->assertTableActionEnabled('addPolicies')
            ->assertTableBulkActionVisible('bulk_remove');

        $user->tenants()->detach($tenant->getKey());
        app(\App\Services\Auth\CapabilityResolver::class)->clearCache();

        $component
            ->call('$refresh')
            ->assertTableActionHidden('addPolicies')
            ->assertTableBulkActionHidden('bulk_remove');
    });

    it('returns 404 and queues nothing when a forged foreign-tenant bulk selection is submitted', function (): void {
        Queue::fake();

        [$user, $tenant] = createUserWithTenant(role: 'owner');

        $this->actingAs($user);
        setAdminPanelContext($tenant);

        $backupSet = BackupSet::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'name' => 'Primary backup',
        ]);

        $inScopeItem = BackupItem::factory()->for($backupSet)->for($tenant)->create();

        $foreignTenant = \App\Models\ManagedEnvironment::factory()->create();
        $foreignBackupSet = BackupSet::factory()->create([
            'managed_environment_id' => (int) $foreignTenant->getKey(),
            'name' => 'Foreign backup',
        ]);
        $foreignBackupItem = BackupItem::factory()->for($foreignBackupSet)->for($foreignTenant)->create();

        $component = Livewire::test(BackupItemsRelationManager::class, [
            'ownerRecord' => $backupSet,
            'pageClass' => EditBackupSet::class,
        ])
            ->assertTableBulkActionVisible('bulk_remove')
            ->assertTableBulkActionEnabled('bulk_remove', [$inScopeItem]);

        expect(fn () => $component->instance()->mountTableBulkAction('bulk_remove', [(string) $inScopeItem->getKey(), (string) $foreignBackupItem->getKey()]))
            ->toThrow(NotFoundHttpException::class);

        Queue::assertNothingPushed();
        Queue::assertNotPushed(RemovePoliciesFromBackupSetJob::class);

        expect(OperationRun::query()->where('type', 'backup_set.update')->exists())->toBeFalse();
    });
});
