<?php

declare(strict_types=1);

use App\Filament\System\Pages\Ops\Runs;
use App\Models\AuditLog;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\Tenant;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\System\SystemOperationRunLinks;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Support\Facades\Notification as NotificationFacade;
use Livewire\Livewire;

uses(RefreshDatabase::class);

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

    Tenant::factory()->create([
        'tenant_id' => null,
        'external_id' => 'platform',
    ]);
});

it('hides triage actions for operators without platform.operations.manage', function () {
    $run = OperationRun::factory()->create([
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'type' => 'inventory_sync',
    ]);

    $viewOnlyUser = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::OPERATIONS_VIEW,
        ],
        'is_active' => true,
    ]);

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

    Livewire::test(Runs::class)
        ->assertTableActionHidden('retry', $run)
        ->assertTableActionHidden('cancel', $run)
        ->assertTableActionHidden('mark_investigated', $run);
});

it('allows manage operators to run triage actions with audit logs and queued-run ux contract', function () {
    NotificationFacade::fake();

    $failedRun = OperationRun::factory()->create([
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'type' => 'inventory_sync',
    ]);

    $manageUser = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::OPERATIONS_VIEW,
            PlatformCapabilities::OPERATIONS_MANAGE,
        ],
        'is_active' => true,
    ]);

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

    Livewire::test(Runs::class)
        ->callTableAction('retry', $failedRun)
        ->assertHasNoTableActionErrors()
        ->assertNotified('Inventory sync queued');

    NotificationFacade::assertNothingSent();
    expect(DatabaseNotification::query()->count())->toBe(0);

    $retriedRun = OperationRun::query()
        ->whereKeyNot((int) $failedRun->getKey())
        ->latest('id')
        ->first();

    expect($retriedRun)->not->toBeNull();
    expect((string) $retriedRun?->status)->toBe(OperationRunStatus::Queued->value);
    expect((int) data_get($retriedRun?->context, 'triage.retry_of_run_id'))->toBe((int) $failedRun->getKey());

    $this->get(SystemOperationRunLinks::view($retriedRun))
        ->assertSuccessful()
        ->assertSee('Run #'.(int) $retriedRun?->getKey());

    Livewire::test(Runs::class)
        ->callTableAction('mark_investigated', $failedRun, data: [
            'reason' => 'Checked by platform operations',
        ])
        ->assertHasNoTableActionErrors();

    expect(AuditLog::query()->where('action', 'platform.system_console.retry')->exists())->toBeTrue();
    expect(AuditLog::query()->where('action', 'platform.system_console.mark_investigated')->exists())->toBeTrue();
});
