<?php

declare(strict_types=1);

use App\Filament\System\Pages\Directory\ViewWorkspace;
use App\Models\AuditLog;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\OperationRunService;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OperationRunType;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

beforeEach(function (): void {
    Filament::setCurrentPanel('system');
    Filament::bootCurrentPanel();
});

it('closes and reopens a workspace through confirmed system actions with audit truth', function (): void {
    $workspace = Workspace::factory()->create(['name' => 'Closure Workspace']);
    $workspaceUser = User::factory()->create();

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

    $tenant = ManagedEnvironment::factory()->active()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'name' => 'Closure ManagedEnvironment',
        'is_current' => true,
    ]);

    ManagedEnvironment::factory()->active()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'name' => 'Second Closure ManagedEnvironment',
        'is_current' => false,
    ]);

    $operator = PlatformUser::factory()->create([
        'name' => 'Platform Directory Operator',
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::DIRECTORY_MANAGE,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionVisible('close_workspace')
        ->assertActionExists('close_workspace', fn (Action $action): bool => $action->isConfirmationRequired())
        ->callAction('close_workspace', data: [
            'reason' => 'Customer requested closure for offboarding.',
        ])
        ->assertHasNoActionErrors()
        ->assertNotified('Workspace closed')
        ->assertActionVisible('reopen_workspace')
        ->assertActionHidden('close_workspace');

    $workspace->refresh();
    $tenant->refresh();

    expect($workspace->isClosed())->toBeTrue()
        ->and($workspace->closed_by_platform_user_id)->toBe((int) $operator->getKey())
        ->and($workspace->closureReason())->toBe('Customer requested closure for offboarding.')
        ->and($tenant->is_current)->toBeFalse()
        ->and(ManagedEnvironment::query()->where('workspace_id', (int) $workspace->getKey())->where('is_current', true)->exists())->toBeFalse()
        ->and(WorkspaceMembership::query()
            ->where('workspace_id', (int) $workspace->getKey())
            ->where('user_id', (int) $workspaceUser->getKey())
            ->exists())->toBeTrue();

    $closeAudit = AuditLog::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('action', AuditActionId::WorkspaceClosed->value)
        ->latest('id')
        ->first();

    expect($closeAudit)->not->toBeNull()
        ->and($closeAudit?->actor_name)->toBe('Platform Directory Operator')
        ->and($closeAudit?->metadata['reason'] ?? null)->toBe('Customer requested closure for offboarding.')
        ->and($closeAudit?->metadata['after_status'] ?? null)->toBe('closed');

    expect(fn () => app(OperationRunService::class)->ensureRun(
        tenant: $tenant->fresh(),
        type: OperationRunType::InventorySync->value,
        inputs: ['scope' => 'workspace_closure_test'],
        initiator: $workspaceUser,
    ))->toThrow(InvalidArgumentException::class, 'Workspace is closed');

    expect(OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->exists())->toBeFalse();

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace->fresh()])
        ->assertActionVisible('reopen_workspace')
        ->assertActionExists('reopen_workspace', fn (Action $action): bool => $action->isConfirmationRequired())
        ->callAction('reopen_workspace', data: [
            'reason' => 'Workspace access is approved again.',
        ])
        ->assertHasNoActionErrors()
        ->assertNotified('Workspace reopened')
        ->assertActionVisible('close_workspace');

    $workspace->refresh();

    expect($workspace->isClosed())->toBeFalse()
        ->and($workspace->closed_by_platform_user_id)->toBeNull()
        ->and($workspace->closureReason())->toBeNull()
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $workspace->getKey())
            ->where('action', AuditActionId::WorkspaceReopened->value)
            ->where('metadata->reason', 'Workspace access is approved again.')
            ->exists())->toBeTrue();
});

it('hides workspace closure mutations from platform users without directory manage capability', function (): void {
    $workspace = Workspace::factory()->create();
    $viewer = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($viewer, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionHidden('close_workspace')
        ->assertActionHidden('reopen_workspace');
});
