<?php

declare(strict_types=1);

use App\Filament\Resources\BackupScheduleResource\Pages\ListBackupSchedules;
use App\Filament\Resources\RestoreRunResource\Pages\ListRestoreRuns;
use App\Filament\Resources\Workspaces\Pages\ListWorkspaces;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
use Tests\TestCase;

final class EmptyStateCtasTest extends TestCase
{
    use RefreshDatabase;

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

        return null;
    }

    public function test_spec090_shows_workspace_empty_state_create_cta_for_users_with_workspace_manage(): void
    {
        $workspace = Workspace::factory()->create([
            'archived_at' => now(),
        ]);

        $user = User::factory()->create();

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

        $user->forceFill([
            'last_workspace_id' => (int) $workspace->getKey(),
        ])->save();

        $this->actingAs($user)
            ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()]);

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

        $action = $this->getTableEmptyStateAction($component, 'create');
        $this->assertNotNull($action);
        $this->assertTrue($action->isVisible());
        $this->assertFalse($action->isDisabled());
    }

    public function test_spec090_disables_workspace_empty_state_create_cta_without_workspace_manage(): void
    {
        $workspace = Workspace::factory()->create([
            'archived_at' => now(),
        ]);

        $user = User::factory()->create();

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

        $user->forceFill([
            'last_workspace_id' => (int) $workspace->getKey(),
        ])->save();

        $this->actingAs($user)
            ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()]);

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

        $action = $this->getTableEmptyStateAction($component, 'create');
        $this->assertNotNull($action);
        $this->assertTrue($action->isVisible());
        $this->assertTrue($action->isDisabled());
    }

    public function test_spec090_shows_backup_schedule_empty_state_create_cta_for_users_with_manage_capability(): void
    {
        [$user, $tenant] = createUserWithTenant(role: 'owner');
        $this->actingAs($user);

        $tenant->makeCurrent();
        Filament::setTenant($tenant, true);

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

        $action = $this->getTableEmptyStateAction($component, 'create');
        $this->assertNotNull($action);
        $this->assertTrue($action->isVisible());
        $this->assertFalse($action->isDisabled());
    }

    public function test_spec090_shows_restore_run_empty_state_create_cta_for_users_with_manage_capability(): void
    {
        [$user, $tenant] = createUserWithTenant(role: 'owner');
        $this->actingAs($user);

        $tenant->makeCurrent();
        Filament::setTenant($tenant, true);

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

        $action = $this->getTableEmptyStateAction($component, 'create');
        $this->assertNotNull($action);
        $this->assertTrue($action->isVisible());
        $this->assertFalse($action->isDisabled());
    }

    public function test_spec090_disables_restore_run_empty_state_create_cta_without_manage_capability(): void
    {
        [$user, $tenant] = createUserWithTenant(role: 'readonly');
        $this->actingAs($user);

        $tenant->makeCurrent();
        Filament::setTenant($tenant, true);

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

        $action = $this->getTableEmptyStateAction($component, 'create');
        $this->assertNotNull($action);
        $this->assertTrue($action->isVisible());
        $this->assertTrue($action->isDisabled());
    }

    public function test_spec090_disables_backup_schedule_empty_state_create_cta_without_manage_capability(): void
    {
        [$user, $tenant] = createUserWithTenant(role: 'readonly');
        $this->actingAs($user);

        $tenant->makeCurrent();
        Filament::setTenant($tenant, true);

        Livewire::test(ListBackupSchedules::class)
            ->assertTableEmptyStateActionsExistInOrder([])
            ->assertActionHidden('create');
    }
}
