<?php

declare(strict_types=1);

use App\Filament\System\Pages\Ops\Controls;
use App\Models\AuditLog;
use App\Models\OperationalControlActivation;
use App\Models\PlatformUser;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\PlatformCapabilities;
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();
});

function makeControlsManager(): PlatformUser
{
    return PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::OPS_CONTROLS_MANAGE,
        ],
        'is_active' => true,
    ]);
}

it('returns 403 for platform users missing the operational controls capability', function (): void {
    $user = PlatformUser::factory()->create([
        'capabilities' => [PlatformCapabilities::ACCESS_SYSTEM_PANEL],
        'is_active' => true,
    ]);

    $this->actingAs($user, 'platform')
        ->get(Controls::getUrl(panel: 'system'))
        ->assertForbidden();
});

it('renders compact card actions and only shows the action that matches the current control state', function (): void {
    $user = makeControlsManager();
    $this->actingAs($user, 'platform');

    $this->get(Controls::getUrl(panel: 'system'))
        ->assertSuccessful()
        ->assertSee("mountAction('pause_restore_execute')", escape: false)
        ->assertDontSee('Findings lifecycle backfill')
        ->assertDontSee("mountAction('pause_findings_lifecycle_backfill')", escape: false)
        ->assertDontSee("mountAction('resume_findings_lifecycle_backfill')", escape: false)
        ->assertDontSee("mountAction('view_history_findings_lifecycle_backfill')", escape: false)
        ->assertDontSee('Pause Restore execution')
        ->assertDontSee('Resume Restore execution');

    OperationalControlActivation::factory()->forGlobalScope()->create([
        'control_key' => 'restore.execute',
        'reason_text' => 'Paused for compact action rendering coverage.',
    ]);

    $this->get(Controls::getUrl(panel: 'system'))
        ->assertSuccessful()
        ->assertSee("mountAction('resume_restore_execute')", escape: false)
        ->assertDontSee("mountAction('pause_restore_execute')", escape: false)
        ->assertDontSee('Findings lifecycle backfill');
});

it('previews, pauses, updates, resumes, and exposes on-demand history for restore execution', function (): void {
    $workspaceA = Workspace::factory()->create(['name' => 'Acme']);
    $workspaceB = Workspace::factory()->create(['name' => 'Bravo']);

    ManagedEnvironment::factory()->count(2)->create(['workspace_id' => (int) $workspaceA->getKey()]);
    ManagedEnvironment::factory()->count(1)->create(['workspace_id' => (int) $workspaceB->getKey()]);

    $user = makeControlsManager();
    $this->actingAs($user, 'platform');

    $component = Livewire::test(Controls::class)
        ->assertActionExists('pause_restore_execute', fn (Action $action): bool => $action->isConfirmationRequired())
        ->assertActionExists('resume_restore_execute', fn (Action $action): bool => $action->isConfirmationRequired())
        ->assertActionExists('view_history_restore_execute', fn (Action $action): bool => $action->getLabel() === 'View Restore execution history');

    $preview = $component->instance()->scopeImpactPreview('restore.execute', 'global', null);

    expect($preview['workspace_count'])->toBe(2)
        ->and($preview['tenant_count'])->toBe(3)
        ->and($preview['summary'])->toContain('2 workspaces')
        ->and($preview['summary'])->toContain('3 tenants');

    $component
        ->callAction('pause_restore_execute', data: [
            'scope_type' => 'global',
            'reason_text' => 'Paused for incident review.',
            'expires_at' => now()->addDay()->toDateTimeString(),
        ])
        ->assertNotified('Restore execution paused');

    $activation = OperationalControlActivation::query()
        ->forControl('restore.execute')
        ->forGlobalScope()
        ->first();

    expect($activation)->not->toBeNull()
        ->and($activation?->reason_text)->toBe('Paused for incident review.');

    $summary = $component->instance()->controlSummary('restore.execute');

    expect($summary['effective_state'])->toBe('paused')
        ->and($summary['active_activations'])->toHaveCount(1)
        ->and($summary['active_activations'][0]['owner_name'])->toBe($user->name);

    $component
        ->callAction('pause_restore_execute', data: [
            'scope_type' => 'global',
            'reason_text' => 'Updated incident review scope.',
            'expires_at' => now()->addDays(2)->toDateTimeString(),
        ])
        ->assertNotified('Restore execution updated');

    expect($activation?->fresh()?->reason_text)->toBe('Updated incident review scope.');

    $component
        ->callAction('resume_restore_execute', data: [
            'scope_type' => 'global',
        ])
        ->assertNotified('Restore execution resumed');

    expect(OperationalControlActivation::query()
        ->forControl('restore.execute')
        ->forGlobalScope()
        ->count())->toBe(0);

    $audits = AuditLog::query()
        ->whereIn('action', [
            AuditActionId::OperationalControlPaused->value,
            AuditActionId::OperationalControlUpdated->value,
            AuditActionId::OperationalControlResumed->value,
        ])
        ->where('metadata->control_key', 'restore.execute')
        ->orderBy('id')
        ->get();

    expect($audits)->toHaveCount(3)
        ->and($audits->pluck('workspace_id')->unique()->all())->toBe([null])
        ->and($audits->pluck('managed_environment_id')->unique()->all())->toBe([null])
        ->and($audits[0]->action)->toBe(AuditActionId::OperationalControlPaused->value)
        ->and($audits[1]->action)->toBe(AuditActionId::OperationalControlUpdated->value)
        ->and($audits[2]->action)->toBe(AuditActionId::OperationalControlResumed->value);

    $component
        ->mountAction('view_history_restore_execute')
        ->assertActionMounted('view_history_restore_execute');
});

it('supports workspace-scoped pauses and removes expired conflicting activations before replacement writes', function (): void {
    $workspaceA = Workspace::factory()->create(['name' => 'Acme']);
    $workspaceB = Workspace::factory()->create(['name' => 'Bravo']);

    ManagedEnvironment::factory()->count(2)->create(['workspace_id' => (int) $workspaceA->getKey()]);
    ManagedEnvironment::factory()->count(1)->create(['workspace_id' => (int) $workspaceB->getKey()]);

    $expired = OperationalControlActivation::factory()->workspaceScoped()->create([
        'control_key' => 'restore.execute',
        'workspace_id' => (int) $workspaceA->getKey(),
        'reason_text' => 'Expired pause.',
        'expires_at' => now()->subHour(),
    ]);

    $user = makeControlsManager();
    $this->actingAs($user, 'platform');

    $component = Livewire::test(Controls::class)
        ->assertActionExists('pause_restore_execute', fn (Action $action): bool => $action->isConfirmationRequired())
        ->assertActionExists('resume_restore_execute', fn (Action $action): bool => $action->isConfirmationRequired());

    $preview = $component->instance()->scopeImpactPreview('restore.execute', 'workspace', (int) $workspaceA->getKey());

    expect($preview['workspace_count'])->toBe(1)
        ->and($preview['tenant_count'])->toBe(2)
        ->and($preview['summary'])->toContain('Acme');

    $component
        ->callAction('pause_restore_execute', data: [
            'scope_type' => 'workspace',
            'workspace_id' => (int) $workspaceA->getKey(),
            'reason_text' => 'Paused for workspace restore maintenance.',
            'expires_at' => now()->addDay()->toDateTimeString(),
        ])
        ->assertNotified('Restore execution paused');

    expect(OperationalControlActivation::query()->whereKey((int) $expired->getKey())->exists())->toBeFalse();

    $activation = OperationalControlActivation::query()
        ->forControl('restore.execute')
        ->forWorkspaceScope((int) $workspaceA->getKey())
        ->notExpired()
        ->first();

    expect($activation)->not->toBeNull()
        ->and((int) ($activation?->workspace_id ?? 0))->toBe((int) $workspaceA->getKey());

    $component
        ->callAction('pause_restore_execute', data: [
            'scope_type' => 'workspace',
            'workspace_id' => (int) $workspaceA->getKey(),
            'reason_text' => 'Updated workspace restore maintenance.',
            'expires_at' => now()->addDays(3)->toDateTimeString(),
        ])
        ->assertNotified('Restore execution updated');

    expect($activation?->fresh()?->reason_text)->toBe('Updated workspace restore maintenance.');

    $component
        ->callAction('resume_restore_execute', data: [
            'scope_type' => 'workspace',
            'workspace_id' => (int) $workspaceA->getKey(),
        ])
        ->assertNotified('Restore execution resumed');

    expect(OperationalControlActivation::query()
        ->forControl('restore.execute')
        ->forWorkspaceScope((int) $workspaceA->getKey())
        ->count())->toBe(0);

    $audits = AuditLog::query()
        ->whereIn('action', [
            AuditActionId::OperationalControlPaused->value,
            AuditActionId::OperationalControlUpdated->value,
            AuditActionId::OperationalControlResumed->value,
        ])
        ->where('metadata->control_key', 'restore.execute')
        ->orderBy('id')
        ->get();

    expect($audits)->toHaveCount(3)
        ->and($audits[0]->workspace_id)->toBe((int) $workspaceA->getKey())
        ->and($audits[0]->managed_environment_id)->toBeNull();
});