<?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\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OperationRunType;
use App\Support\Workspaces\WorkspaceOverviewBuilder;

it('prioritizes governance-critical tenants above activity-only and alert-only items', function (): void {
    $tenantGovernance = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenantGovernance] = createUserWithTenant($tenantGovernance, role: 'owner', workspaceRole: 'readonly');
    [$profile, $snapshot] = seedActiveBaselineForTenant($tenantGovernance);
    seedBaselineCompareRun($tenantGovernance, $profile, $snapshot, workspaceOverviewCompareCoverage());
    $tenantGovernanceBackup = workspaceOverviewSeedHealthyBackup($tenantGovernance, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantGovernance, $tenantGovernanceBackup, 'completed');

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

    $tenantActivity = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantGovernance->workspace_id,
        'name' => 'Busy ManagedEnvironment',
    ]);
    createUserWithTenant($tenantActivity, $user, role: 'owner', workspaceRole: 'readonly');
    [$activityProfile, $activitySnapshot] = seedActiveBaselineForTenant($tenantActivity);
    seedBaselineCompareRun($tenantActivity, $activityProfile, $activitySnapshot, workspaceOverviewCompareCoverage());
    $tenantActivityBackup = workspaceOverviewSeedHealthyBackup($tenantActivity, [
        'completed_at' => now()->subMinutes(14),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantActivity, $tenantActivityBackup, 'completed');

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenantActivity->getKey(),
        'workspace_id' => (int) $tenantActivity->workspace_id,
        'type' => OperationRunType::InventorySync->value,
        'status' => OperationRunStatus::Running->value,
        'outcome' => OperationRunOutcome::Pending->value,
    ]);

    $tenantAlerts = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantGovernance->workspace_id,
        'name' => 'Alerts ManagedEnvironment',
    ]);
    createUserWithTenant($tenantAlerts, $user, role: 'owner', workspaceRole: 'readonly');
    [$alertsProfile, $alertsSnapshot] = seedActiveBaselineForTenant($tenantAlerts);
    seedBaselineCompareRun($tenantAlerts, $alertsProfile, $alertsSnapshot, workspaceOverviewCompareCoverage());
    $tenantAlertsBackup = workspaceOverviewSeedHealthyBackup($tenantAlerts, [
        'completed_at' => now()->subMinutes(13),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantAlerts, $tenantAlertsBackup, 'completed');

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

    $workspace = $tenantGovernance->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);

    expect($overview['calmness']['is_calm'])->toBeFalse()
        ->and($overview['attention_items'])->toHaveCount(3)
        ->and($overview['attention_items'][0]['key'])->toBe('tenant_overdue_findings')
        ->and($overview['attention_items'][0]['tenant_label'])->toBe((string) $tenantGovernance->name)
        ->and($overview['attention_items'][1]['key'])->toBe('tenant_active_operations')
        ->and($overview['attention_items'][2]['key'])->toBe('tenant_alert_delivery_failures');
});

it('surfaces expiring governance and stale compare posture as governance attention without a false calm state', function (): void {
    $tenantExpiring = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenantExpiring] = createUserWithTenant($tenantExpiring, role: 'owner', workspaceRole: 'readonly');
    [$expiringProfile, $expiringSnapshot] = seedActiveBaselineForTenant($tenantExpiring);
    seedBaselineCompareRun($tenantExpiring, $expiringProfile, $expiringSnapshot, workspaceOverviewCompareCoverage());
    $tenantExpiringBackup = workspaceOverviewSeedHealthyBackup($tenantExpiring, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantExpiring, $tenantExpiringBackup, 'completed');

    $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' => 'Governance nearly expired',
        'approval_reason' => 'Accepted for a short window',
        '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) $tenantExpiring->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),
    );
    $tenantStaleBackup = workspaceOverviewSeedHealthyBackup($tenantStale, [
        'completed_at' => now()->subMinutes(14),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantStale, $tenantStaleBackup, 'completed');

    $workspace = $tenantExpiring->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $items = collect($overview['attention_items'])->keyBy('key');

    expect($overview['calmness']['is_calm'])->toBeFalse()
        ->and($items->keys()->all())->toContain('tenant_expiring_governance', 'tenant_compare_attention')
        ->and($items->get('tenant_compare_attention')['badge'])->toBe('Baseline')
        ->and($items->get('tenant_expiring_governance')['family'])->toBe('governance');
});

it('ranks lapsed governance and failed compare posture ahead of high-severity findings', function (): void {
    $tenantLapsed = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenantLapsed] = createUserWithTenant($tenantLapsed, role: 'owner', workspaceRole: 'readonly');
    [$lapsedProfile, $lapsedSnapshot] = seedActiveBaselineForTenant($tenantLapsed);
    seedBaselineCompareRun($tenantLapsed, $lapsedProfile, $lapsedSnapshot, workspaceOverviewCompareCoverage());
    $tenantLapsedBackup = workspaceOverviewSeedHealthyBackup($tenantLapsed, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantLapsed, $tenantLapsedBackup, 'completed');

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

    $tenantFailedCompare = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantLapsed->workspace_id,
        'name' => 'Failed Compare ManagedEnvironment',
    ]);
    createUserWithTenant($tenantFailedCompare, $user, role: 'owner', workspaceRole: 'readonly');
    [$failedProfile, $failedSnapshot] = seedActiveBaselineForTenant($tenantFailedCompare);
    seedBaselineCompareRun(
        $tenantFailedCompare,
        $failedProfile,
        $failedSnapshot,
        workspaceOverviewCompareCoverage(),
        outcome: OperationRunOutcome::Failed->value,
    );
    $tenantFailedBackup = workspaceOverviewSeedHealthyBackup($tenantFailedCompare, [
        'completed_at' => now()->subMinutes(14),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantFailedCompare, $tenantFailedBackup, 'completed');

    $tenantHighSeverity = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantLapsed->workspace_id,
        'name' => 'High Severity ManagedEnvironment',
    ]);
    createUserWithTenant($tenantHighSeverity, $user, role: 'owner', workspaceRole: 'readonly');
    [$highProfile, $highSnapshot] = seedActiveBaselineForTenant($tenantHighSeverity);
    seedBaselineCompareRun($tenantHighSeverity, $highProfile, $highSnapshot, workspaceOverviewCompareCoverage());
    $tenantHighBackup = workspaceOverviewSeedHealthyBackup($tenantHighSeverity, [
        'completed_at' => now()->subMinutes(13),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantHighSeverity, $tenantHighBackup, 'completed');

    Finding::factory()->for($tenantHighSeverity)->create([
        'workspace_id' => (int) $tenantHighSeverity->workspace_id,
        'status' => Finding::STATUS_TRIAGED,
        'severity' => Finding::SEVERITY_CRITICAL,
    ]);

    $workspace = $tenantLapsed->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);

    expect(collect($overview['attention_items'])->pluck('key')->take(3)->all())
        ->toBe([
            'tenant_lapsed_governance',
            'tenant_compare_attention',
            'tenant_high_severity_findings',
        ]);
});

it('keeps governance-first ordering while inserting backup and recovery attention ahead of activity-only items', function (): void {
    $governanceTenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $governanceTenant] = createUserWithTenant($governanceTenant, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($governanceTenant);
    $governanceBackup = workspaceOverviewSeedHealthyBackup($governanceTenant, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($governanceTenant, $governanceBackup, 'completed');

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

    $backupTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $governanceTenant->workspace_id,
        'name' => 'Backup ManagedEnvironment',
    ]);
    createUserWithTenant($backupTenant, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($backupTenant);

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

    $operationsTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $governanceTenant->workspace_id,
        'name' => 'Operations ManagedEnvironment',
    ]);
    createUserWithTenant($operationsTenant, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($operationsTenant);
    $operationsBackup = workspaceOverviewSeedHealthyBackup($operationsTenant, [
        'completed_at' => now()->subMinutes(14),
    ]);
    workspaceOverviewSeedRestoreHistory($operationsTenant, $operationsBackup, 'completed');

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $operationsTenant->getKey(),
        'workspace_id' => (int) $operationsTenant->workspace_id,
        'type' => OperationRunType::InventorySync->value,
        'status' => OperationRunStatus::Running->value,
        'outcome' => OperationRunOutcome::Pending->value,
    ]);

    $overview = app(WorkspaceOverviewBuilder::class)->build($governanceTenant->workspace()->firstOrFail(), $user);
    $keys = collect($overview['attention_items'])->pluck('key')->all();

    expect($keys[0])->toBe('tenant_overdue_findings')
        ->and(array_search('tenant_active_operations', $keys, true))->toBeGreaterThan(array_search('tenant_recovery_weakened', $keys, true))
        ->and(array_search('tenant_active_operations', $keys, true))->toBeGreaterThan(array_search('tenant_backup_absent', $keys, true));
});
