<?php

declare(strict_types=1);

use App\Filament\System\Pages\Dashboard;
use App\Filament\System\Widgets\CustomerHealthKpis;
use App\Models\Finding;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\ProductUsageEvent;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\ProductTelemetry\ProductUsageEventCatalog;
use App\Support\SystemConsole\SystemConsoleWindow;
use Carbon\CarbonImmutable;
use Filament\Facades\Filament;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

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

    CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-04-27 12:00:00'));
});

afterEach(function (): void {
    CarbonImmutable::setTestNow();
});

it('renders aggregate healthy, warning, critical, and unknown counts with a visible time-basis cue', function (): void {
    actingAsCustomerHealthSystemUser();

    $baselineStats = customerHealthStats(Livewire::withQueryParams([
        'window' => SystemConsoleWindow::LastDay,
    ])->test(CustomerHealthKpis::class));

    seedCustomerHealthWorkspace('Healthy Workspace');
    seedCustomerHealthWorkspace('Warning Workspace', recentUsage: false, historicalUsage: true);
    seedCustomerHealthWorkspace('Critical Workspace', failedRun: true);
    seedCustomerHealthWorkspace('Unknown Workspace', recentRun: false, readyReviewPack: false);

    $stats = customerHealthStats(Livewire::withQueryParams([
        'window' => SystemConsoleWindow::LastDay,
    ])->test(CustomerHealthKpis::class));

    expect((int) $stats['Healthy']['value'] - (int) $baselineStats['Healthy']['value'])->toBe(1)
        ->and($stats['Healthy']['description'])->toBe('Operational stability, review-pack readiness, and engagement freshness honor Last 24 hours.')
        ->and((int) $stats['Warning']['value'] - (int) $baselineStats['Warning']['value'])->toBe(1)
        ->and($stats['Warning']['description'])->toBe('Onboarding readiness, provider health, and governance pressure stay point-in-time.')
        ->and((int) $stats['Critical']['value'] - (int) $baselineStats['Critical']['value'])->toBe(1)
        ->and((int) $stats['Unknown']['value'] - (int) $baselineStats['Unknown']['value'])->toBe(1)
        ->and($stats['Unknown']['description'])->toBe('Missing or stale inputs stay explicit instead of silently reading healthy.');
});

it('registers the customer health widget on the system dashboard for authorized users', function (): void {
    $user = actingAsCustomerHealthSystemUser();

    $response = $this->actingAs($user, 'platform')->get(Dashboard::getUrl(panel: 'system'));

    $response->assertSuccessful()
        ->assertSee('Customer health')
        ->assertSeeLivewire(CustomerHealthKpis::class);
});

/**
 * @return array<string, array{value:string,description:string|null}>
 */
function customerHealthStats($component): array
{
    $method = new ReflectionMethod(CustomerHealthKpis::class, 'getStats');
    $method->setAccessible(true);

    return collect($method->invoke($component->instance()))
        ->mapWithKeys(fn (Stat $stat): array => [
            (string) $stat->getLabel() => [
                'value' => (string) $stat->getValue(),
                'description' => $stat->getDescription(),
            ],
        ])
        ->all();
}

function actingAsCustomerHealthSystemUser(): PlatformUser
{
    $user = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::CONSOLE_VIEW,
        ],
        'is_active' => true,
    ]);

    test()->actingAs($user, 'platform');

    return $user;
}

/**
 * @return array{workspace: Workspace, tenant: ManagedEnvironment}
 */
function seedCustomerHealthWorkspace(
    string $workspaceName,
    bool $readyReviewPack = true,
    bool $recentUsage = true,
    bool $historicalUsage = false,
    bool $recentRun = true,
    bool $failedRun = false,
): array {
    $workspace = Workspace::factory()->create(['name' => $workspaceName]);
    $tenant = ManagedEnvironment::factory()->for($workspace)->create([
        'name' => $workspaceName.' ManagedEnvironment',
        'status' => ManagedEnvironment::STATUS_ACTIVE,
    ]);

    ProviderConnection::factory()
        ->for($tenant)
        ->verifiedHealthy()
        ->create([
            'workspace_id' => (int) $workspace->getKey(),
            'is_default' => true,
        ]);

    if ($readyReviewPack) {
        ReviewPack::factory()
            ->for($tenant)
            ->ready()
            ->create([
                'workspace_id' => (int) $workspace->getKey(),
                'created_at' => now()->subHour(),
                'generated_at' => now()->subHour(),
                'expires_at' => now()->addDays(30),
            ]);
    }

    if ($recentUsage) {
        ProductUsageEvent::factory()
            ->for($tenant)
            ->forEvent(ProductUsageEventCatalog::ONBOARDING_CHECKPOINT_COMPLETED)
            ->create([
                'workspace_id' => (int) $workspace->getKey(),
                'occurred_at' => now()->subMinutes(20),
            ]);
    } elseif ($historicalUsage) {
        ProductUsageEvent::factory()
            ->for($tenant)
            ->forEvent(ProductUsageEventCatalog::ONBOARDING_CHECKPOINT_COMPLETED)
            ->create([
                'workspace_id' => (int) $workspace->getKey(),
                'occurred_at' => now()->subDays(3),
            ]);
    }

    if ($recentRun) {
        OperationRun::factory()
            ->forTenant($tenant)
            ->create([
                'workspace_id' => (int) $workspace->getKey(),
                'status' => OperationRunStatus::Completed->value,
                'outcome' => $failedRun ? OperationRunOutcome::Failed->value : OperationRunOutcome::Succeeded->value,
                'created_at' => now()->subMinutes(10),
                'started_at' => now()->subMinutes(15),
                'completed_at' => now()->subMinutes(5),
            ]);
    }

    Finding::factory()
        ->for($tenant)
        ->closed()
        ->create([
            'severity' => Finding::SEVERITY_LOW,
        ]);

    return [
        'workspace' => $workspace,
        'tenant' => $tenant,
    ];
}