<?php

use App\Filament\Resources\BackupSetResource;
use App\Filament\Resources\BackupSetResource\Pages\ListBackupSets;
use App\Models\BackupSet;
use App\Models\ManagedEnvironment;
use App\Support\Auth\UiTooltips;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Livewire\Livewire;

function getTableEmptyStateAction($component, string $name): ?\Filament\Actions\Action
{
    foreach ($component->instance()->getTable()->getEmptyStateActions() as $action) {
        if ($action instanceof \Filament\Actions\Action && $action->getName() === $name) {
            return $action;
        }
    }

    return null;
}

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Http::preventStrayRequests();
});

test('non-members are denied access to BackupSet tenant routes (404)', function () {
    $tenant = ManagedEnvironment::factory()->create();
    $otherTenant = ManagedEnvironment::factory()->create();

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

    $this->actingAs($user)
        ->get(BackupSetResource::getUrl('index', panel: 'admin', tenant: $tenant))
        ->assertStatus(404);
});

test('members without capability see BackupSet actions disabled with standard tooltip and cannot execute', function () {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = createUserWithTenant($tenant, role: 'readonly');

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'status' => 'completed',
        'deleted_at' => null,
    ]);

    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListBackupSets::class)
        ->assertTableActionDisabled('archive', $backupSet)
        ->assertTableActionExists('archive', fn ($action): bool => $action->getTooltip() === UiTooltips::insufficientPermission(), $backupSet)
        ->callTableAction('archive', $backupSet);

    expect($backupSet->fresh()->trashed())->toBeFalse();
});

test('members with capability can execute BackupSet actions', function () {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = createUserWithTenant($tenant, role: 'owner');

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'status' => 'completed',
        'deleted_at' => null,
    ]);

    Filament::setTenant($tenant, true);

    Livewire::actingAs($user)
        ->test(ListBackupSets::class)
        ->assertTableActionEnabled('archive', $backupSet)
        ->callTableAction('archive', $backupSet);

    expect($backupSet->fresh()->trashed())->toBeTrue();
});

test('backup sets list shows empty state create action enabled for members with sync capability', function () {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = createUserWithTenant($tenant, role: 'owner');

    Filament::setTenant($tenant, true);

    $component = Livewire::actingAs($user)
        ->test(ListBackupSets::class)
        ->assertTableEmptyStateActionsExistInOrder(['create']);

    $action = getTableEmptyStateAction($component, 'create');
    expect($action)->not->toBeNull();
    expect($action->isVisible())->toBeTrue();
    expect($action->isDisabled())->toBeFalse();
    expect($action->getLabel())->toBe('Create backup set');
});

test('backup sets list shows empty state create action disabled for members without sync capability', function () {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = createUserWithTenant($tenant, role: 'readonly');

    Filament::setTenant($tenant, true);

    $component = Livewire::actingAs($user)
        ->test(ListBackupSets::class)
        ->assertTableEmptyStateActionsExistInOrder(['create']);

    $action = getTableEmptyStateAction($component, 'create');
    expect($action)->not->toBeNull();
    expect($action->isVisible())->toBeTrue();
    expect($action->isDisabled())->toBeTrue();
    expect($action->getTooltip())->toBe(UiTooltips::insufficientPermission());
});

test('readonly members still see backup quality truth on the backup-set list', function () {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = createUserWithTenant($tenant, role: 'readonly');

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'status' => 'completed',
        'item_count' => 1,
    ]);

    \App\Models\BackupItem::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'backup_set_id' => $backupSet->getKey(),
        'payload' => [],
        'metadata' => [
            'source' => 'metadata_only',
        ],
        'assignments' => [],
    ]);

    Filament::setTenant($tenant, true);

    $this->actingAs($user)
        ->get(BackupSetResource::getUrl('index', tenant: $tenant))
        ->assertOk()
        ->assertSee('Backup quality')
        ->assertSee('1 metadata-only');
});
