<?php

declare(strict_types=1);

use App\Models\AlertDelivery;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Support\Workspaces\WorkspaceOverviewBuilder;
use Carbon\CarbonImmutable;

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

it('counts governance attention by affected tenant instead of raw issue totals', function (): void {
    $tenantOverdue = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenantOverdue] = createUserWithTenant($tenantOverdue, role: 'owner', workspaceRole: 'readonly');
    [$overdueProfile, $overdueSnapshot] = seedActiveBaselineForTenant($tenantOverdue);
    seedBaselineCompareRun($tenantOverdue, $overdueProfile, $overdueSnapshot, workspaceOverviewCompareCoverage());

    Finding::factory()->count(3)->for($tenantOverdue)->create([
        'workspace_id' => (int) $tenantOverdue->workspace_id,
        'status' => Finding::STATUS_TRIAGED,
        'due_at' => now()->subDay(),
    ]);

    $tenantExpiring = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantOverdue->workspace_id,
        'name' => 'Expiring ManagedEnvironment',
    ]);
    createUserWithTenant($tenantExpiring, $user, role: 'owner', workspaceRole: 'readonly');
    [$expiringProfile, $expiringSnapshot] = seedActiveBaselineForTenant($tenantExpiring);
    seedBaselineCompareRun($tenantExpiring, $expiringProfile, $expiringSnapshot, workspaceOverviewCompareCoverage());

    $finding = Finding::factory()->riskAccepted()->create([
        'workspace_id' => (int) $tenantExpiring->workspace_id,
        'managed_environment_id' => (int) $tenantExpiring->getKey(),
    ]);

    FindingException::query()->create([
        'workspace_id' => (int) $tenantExpiring->workspace_id,
        'managed_environment_id' => (int) $tenantExpiring->getKey(),
        'finding_id' => (int) $finding->getKey(),
        'requested_by_user_id' => (int) $user->getKey(),
        'owner_user_id' => (int) $user->getKey(),
        'approved_by_user_id' => (int) $user->getKey(),
        'status' => FindingException::STATUS_EXPIRING,
        'current_validity_state' => FindingException::VALIDITY_EXPIRING,
        'request_reason' => 'Pending governance review',
        'approval_reason' => 'Short lived exception',
        'requested_at' => now()->subDays(2),
        'approved_at' => now()->subDay(),
        'effective_from' => now()->subDay(),
        'expires_at' => now()->addDay(),
        'review_due_at' => now()->addDay(),
        'evidence_summary' => ['reference_count' => 0],
    ]);

    $tenantStale = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantOverdue->workspace_id,
        'name' => 'Stale ManagedEnvironment',
    ]);
    createUserWithTenant($tenantStale, $user, role: 'owner', workspaceRole: 'readonly');
    [$staleProfile, $staleSnapshot] = seedActiveBaselineForTenant($tenantStale);
    seedBaselineCompareRun(
        $tenantStale,
        $staleProfile,
        $staleSnapshot,
        workspaceOverviewCompareCoverage(),
        completedAt: now()->subDays(10),
    );

    $tenantFailedCompare = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantOverdue->workspace_id,
        'name' => 'Failed Compare ManagedEnvironment',
    ]);
    createUserWithTenant($tenantFailedCompare, $user, role: 'owner', workspaceRole: 'readonly');
    [$failedProfile, $failedSnapshot] = seedActiveBaselineForTenant($tenantFailedCompare);
    seedBaselineCompareRun(
        $tenantFailedCompare,
        $failedProfile,
        $failedSnapshot,
        workspaceOverviewCompareCoverage(),
        outcome: \App\Support\OperationRunOutcome::Failed->value,
    );

    $workspace = $tenantOverdue->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $metrics = collect($overview['summary_metrics'])->keyBy('key');

    expect($metrics->get('governance_attention_tenants')['value'])->toBe(4)
        ->and($metrics->get('governance_attention_tenants')['category'])->toBe('governance_risk')
        ->and($metrics->get('governance_attention_tenants')['destination']['kind'])->toBe('choose_environment');
});

it('keeps activity and alerts metrics separate from governance risk', function (): void {
    $tenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'readonly');
    [$profile, $snapshot] = seedActiveBaselineForTenant($tenant);
    seedBaselineCompareRun($tenant, $profile, $snapshot, workspaceOverviewCompareCoverage());

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => \App\Support\OperationRunStatus::Running->value,
        'outcome' => \App\Support\OperationRunOutcome::Pending->value,
    ]);

    AlertDelivery::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => AlertDelivery::STATUS_FAILED,
        'created_at' => now(),
    ]);

    $workspace = $tenant->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $metrics = collect($overview['summary_metrics'])->keyBy('key');

    expect($metrics->get('governance_attention_tenants')['value'])->toBe(0)
        ->and($metrics->get('active_operations')['value'])->toBe(1)
        ->and($metrics->get('active_operations')['category'])->toBe('activity')
        ->and($metrics->get('active_operations')['destination']['kind'])->toBe('operations_index')
        ->and($metrics->get('alert_failures')['value'])->toBe(1)
        ->and($metrics->get('alert_failures')['category'])->toBe('alerts');
});

it('counts backup and recovery attention tenants separately and chooses precise or fallback destinations', function (): void {
    CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 9, 9, 0, 0, 'UTC'));

    $recoveryTenantA = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'name' => 'Recovery ManagedEnvironment A',
    ]);
    [$user, $recoveryTenantA] = createUserWithTenant($recoveryTenantA, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($recoveryTenantA);
    $recoveryTenantABackup = workspaceOverviewSeedHealthyBackup($recoveryTenantA, [
        'completed_at' => now()->subMinutes(20),
    ]);
    workspaceOverviewSeedRestoreHistory($recoveryTenantA, $recoveryTenantABackup, 'follow_up');

    $recoveryTenantB = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $recoveryTenantA->workspace_id,
        'name' => 'Recovery ManagedEnvironment B',
    ]);
    createUserWithTenant($recoveryTenantB, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($recoveryTenantB);
    $recoveryTenantBBackup = workspaceOverviewSeedHealthyBackup($recoveryTenantB, [
        'completed_at' => now()->subMinutes(22),
    ]);
    workspaceOverviewSeedRestoreHistory($recoveryTenantB, $recoveryTenantBBackup, 'failed');

    $backupTenantA = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $recoveryTenantA->workspace_id,
        'name' => 'Backup ManagedEnvironment A',
    ]);
    createUserWithTenant($backupTenantA, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($backupTenantA);
    $backupTenantABackup = workspaceOverviewSeedHealthyBackup($backupTenantA, [
        'completed_at' => now()->subDays(2),
    ]);
    workspaceOverviewSeedRestoreHistory($backupTenantA, $backupTenantABackup, 'completed');

    $backupTenantB = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $recoveryTenantA->workspace_id,
        'name' => 'Backup ManagedEnvironment B',
    ]);
    createUserWithTenant($backupTenantB, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($backupTenantB);
    $backupTenantBBackup = workspaceOverviewSeedHealthyBackup($backupTenantB, [
        'completed_at' => now()->subMinutes(18),
    ], [
        'payload' => [],
        'metadata' => [
            'source' => 'metadata_only',
            'assignments_fetch_failed' => true,
        ],
        'assignments' => [],
    ]);
    workspaceOverviewSeedRestoreHistory($backupTenantB, $backupTenantBBackup, 'completed');

    $calmTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $recoveryTenantA->workspace_id,
        'name' => 'Calm ManagedEnvironment',
    ]);
    createUserWithTenant($calmTenant, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($calmTenant);
    $calmBackup = workspaceOverviewSeedHealthyBackup($calmTenant, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($calmTenant, $calmBackup, 'completed');

    $workspace = $recoveryTenantA->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $metrics = collect($overview['summary_metrics'])->keyBy('key');
    $backupDestination = $metrics->get('backup_attention_tenants')['destination'];
    $recoveryDestination = $metrics->get('recovery_attention_tenants')['destination'];

    expect($metrics->get('backup_attention_tenants')['value'])->toBe(2)
        ->and($metrics->get('backup_attention_tenants')['category'])->toBe('backup_health')
        ->and($metrics->get('backup_attention_tenants')['destination']['kind'])->toBe('choose_environment')
        ->and($metrics->get('backup_attention_tenants')['destination_url'])->toStartWith(\App\Filament\Resources\ManagedEnvironmentResource::getUrl(panel: 'admin'))
        ->and($backupDestination['filters'])->toBe([
            'backup_posture' => ['absent', 'stale', 'degraded'],
            'triage_sort' => 'worst_first',
        ])
        ->and($metrics->get('recovery_attention_tenants')['value'])->toBe(2)
        ->and($metrics->get('recovery_attention_tenants')['category'])->toBe('recovery_evidence')
        ->and($recoveryDestination['kind'])->toBe('choose_environment')
        ->and($metrics->get('recovery_attention_tenants')['destination_url'])->toStartWith(\App\Filament\Resources\ManagedEnvironmentResource::getUrl(panel: 'admin'))
        ->and($recoveryDestination['filters'])->toBe([
            'recovery_evidence' => ['weakened', 'unvalidated'],
            'triage_sort' => 'worst_first',
        ]);
});

it('keeps backup and recovery attention counts at zero for calm visible tenants', function (): void {
    CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 9, 9, 0, 0, 'UTC'));

    $tenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($tenant);
    $backupSet = workspaceOverviewSeedHealthyBackup($tenant, [
        'completed_at' => now()->subMinutes(10),
    ]);
    workspaceOverviewSeedRestoreHistory($tenant, $backupSet, 'completed');

    $workspace = $tenant->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $metrics = collect($overview['summary_metrics'])->keyBy('key');

    expect($metrics->get('backup_attention_tenants')['value'])->toBe(0)
        ->and($metrics->get('recovery_attention_tenants')['value'])->toBe(0)
        ->and($overview['calmness']['checked_domains'])->toContain('backup_health', 'recovery_evidence');
});
