<?php

declare(strict_types=1);

use App\Filament\System\Pages\Dashboard;
use App\Filament\System\Pages\RepairWorkspaceOwners;
use App\Models\AuditLog;
use App\Models\PlatformUser;
use App\Models\SupportAccessGrant;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\Auth\PlatformCapabilities;
use App\Support\Auth\WorkspaceRole;
use Filament\Facades\Filament;
use Livewire\Livewire;

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

    ManagedEnvironment::factory()->create([
        'managed_environment_id' => null,
        'external_id' => 'platform',
        'name' => 'Platform',
    ]);

    config()->set('tenantpilot.break_glass.enabled', true);
    config()->set('tenantpilot.break_glass.ttl_minutes', 15);
});

function spec276_recovery_platform_user(): PlatformUser
{
    return PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::CONSOLE_VIEW,
            PlatformCapabilities::USE_BREAK_GLASS,
        ],
    ]);
}

function spec276_ownerless_workspace_with_target(): array
{
    $workspace = Workspace::factory()->create();
    $targetUser = User::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $targetUser->getKey(),
        'role' => WorkspaceRole::Operator->value,
    ]);

    return [$workspace, $targetUser];
}

it('blocks owner repair when break-glass is active but recovery-scoped support access is missing', function (): void {
    $platformUser = spec276_recovery_platform_user();
    [$workspace, $targetUser] = spec276_ownerless_workspace_with_target();

    $this->actingAs($platformUser, 'platform');

    Livewire::test(Dashboard::class)
        ->callAction('enter_break_glass', data: [
            'reason' => 'Recover workspace ownership',
        ]);

    Livewire::test(RepairWorkspaceOwners::class)
        ->callAction('assign_owner', data: [
            'workspace_id' => (int) $workspace->getKey(),
            'target_user_id' => (int) $targetUser->getKey(),
            'reason' => 'Fix ownerless workspace',
        ])
        ->assertHasErrors();

    expect(WorkspaceMembership::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('user_id', (int) $targetUser->getKey())
        ->value('role'))->toBe(WorkspaceRole::Operator->value);
});

it('does not allow audit-view support access to satisfy the owner-repair boundary', function (): void {
    $platformUser = spec276_recovery_platform_user();
    [$workspace, $targetUser] = spec276_ownerless_workspace_with_target();

    SupportAccessGrant::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'requested_by_platform_user_id' => (int) $platformUser->getKey(),
        'scope' => SupportAccessGrant::SCOPE_AUDIT_VIEW,
    ]);

    $this->actingAs($platformUser, 'platform');

    Livewire::test(Dashboard::class)
        ->callAction('enter_break_glass', data: [
            'reason' => 'Recover workspace ownership',
        ]);

    Livewire::test(RepairWorkspaceOwners::class)
        ->callAction('assign_owner', data: [
            'workspace_id' => (int) $workspace->getKey(),
            'target_user_id' => (int) $targetUser->getKey(),
            'reason' => 'Fix ownerless workspace',
        ])
        ->assertHasErrors();
});

it('allows owner repair only when break-glass and active workspace-recovery support access are both present', function (): void {
    $platformUser = spec276_recovery_platform_user();
    [$workspace, $targetUser] = spec276_ownerless_workspace_with_target();

    $supportGrant = SupportAccessGrant::factory()->activeRecovery()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'requested_by_platform_user_id' => (int) $platformUser->getKey(),
    ]);

    $this->actingAs($platformUser, 'platform');

    Livewire::test(Dashboard::class)
        ->callAction('enter_break_glass', data: [
            'reason' => 'Recover workspace ownership',
        ]);

    Livewire::test(RepairWorkspaceOwners::class)
        ->callAction('assign_owner', data: [
            'workspace_id' => (int) $workspace->getKey(),
            'target_user_id' => (int) $targetUser->getKey(),
            'reason' => 'Fix ownerless workspace',
        ])
        ->assertHasNoActionErrors()
        ->assertNotified('Owner assigned');

    expect(WorkspaceMembership::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('user_id', (int) $targetUser->getKey())
        ->value('role'))->toBe(WorkspaceRole::Owner->value);

    expect(AuditLog::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('action', 'workspace_membership.break_glass.assign_owner')
        ->whereJsonContains('metadata->support_access_grant_id', (int) $supportGrant->getKey())
        ->exists())->toBeTrue();
});
