<?php

declare(strict_types=1);

use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\ManagedEnvironmentResource\Pages\ListManagedEnvironments;
use App\Filament\Widgets\Dashboard\NeedsAttention as TenantNeedsAttention;
use App\Filament\Widgets\Workspace\WorkspaceNeedsAttention;
use App\Models\AlertDelivery;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OperationRunType;
use App\Support\Tenants\TenantRecoveryTriagePresentation;
use App\Support\Workspaces\WorkspaceContext;
use App\Support\Workspaces\WorkspaceOverviewBuilder;
use Carbon\CarbonImmutable;
use Filament\Facades\Filament;
use Livewire\Livewire;

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

it('preserves canonical findings, compare, alerts, and operations drill-through continuity from the workspace overview', function (): void {
    $tenantDashboard = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$user, $tenantDashboard] = createUserWithTenant($tenantDashboard, role: 'owner', workspaceRole: 'readonly');
    [$dashboardProfile, $dashboardSnapshot] = seedActiveBaselineForTenant($tenantDashboard);
    seedBaselineCompareRun($tenantDashboard, $dashboardProfile, $dashboardSnapshot, workspaceOverviewCompareCoverage());
    $tenantDashboardBackup = workspaceOverviewSeedHealthyBackup($tenantDashboard, [
        'completed_at' => now()->subMinutes(15),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantDashboard, $tenantDashboardBackup, 'completed');

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

    $tenantFindings = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantDashboard->workspace_id,
    ]);
    createUserWithTenant($tenantFindings, $user, role: 'owner', workspaceRole: 'readonly');
    [$findingsProfile, $findingsSnapshot] = seedActiveBaselineForTenant($tenantFindings);
    seedBaselineCompareRun($tenantFindings, $findingsProfile, $findingsSnapshot, workspaceOverviewCompareCoverage());
    $tenantFindingsBackup = workspaceOverviewSeedHealthyBackup($tenantFindings, [
        'completed_at' => now()->subMinutes(14),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantFindings, $tenantFindingsBackup, 'completed');

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

    $tenantCompare = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantDashboard->workspace_id,
        'name' => 'Compare ManagedEnvironment',
    ]);
    createUserWithTenant($tenantCompare, $user, role: 'owner', workspaceRole: 'readonly');
    [$compareProfile, $compareSnapshot] = seedActiveBaselineForTenant($tenantCompare);
    seedBaselineCompareRun(
        $tenantCompare,
        $compareProfile,
        $compareSnapshot,
        workspaceOverviewCompareCoverage(),
        completedAt: now()->subDays(10),
    );
    $tenantCompareBackup = workspaceOverviewSeedHealthyBackup($tenantCompare, [
        'completed_at' => now()->subMinutes(13),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantCompare, $tenantCompareBackup, 'completed');

    $tenantOperations = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantDashboard->workspace_id,
        'name' => 'Operations ManagedEnvironment',
    ]);
    createUserWithTenant($tenantOperations, $user, role: 'owner', workspaceRole: 'readonly');
    [$operationsProfile, $operationsSnapshot] = seedActiveBaselineForTenant($tenantOperations);
    seedBaselineCompareRun($tenantOperations, $operationsProfile, $operationsSnapshot, workspaceOverviewCompareCoverage());
    $tenantOperationsBackup = workspaceOverviewSeedHealthyBackup($tenantOperations, [
        'completed_at' => now()->subMinutes(12),
    ]);
    workspaceOverviewSeedRestoreHistory($tenantOperations, $tenantOperationsBackup, 'completed');

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenantOperations->getKey(),
        'workspace_id' => (int) $tenantOperations->workspace_id,
        'type' => OperationRunType::PolicySync->value,
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
    ]);

    $tenantAlerts = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $tenantDashboard->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(11),
    ]);
    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 = $tenantDashboard->workspace()->firstOrFail();
    $overview = app(WorkspaceOverviewBuilder::class)->build($workspace, $user);
    $items = collect($overview['attention_items'])->keyBy('key');

    expect($items->get('tenant_lapsed_governance')['destination']['kind'])->toBe('tenant_dashboard')
        ->and($items->get('tenant_overdue_findings')['destination']['kind'])->toBe('tenant_findings')
        ->and($items->get('tenant_overdue_findings')['destination']['url'])->toContain('tab=overdue')
        ->and($items->get('tenant_compare_attention')['destination']['kind'])->toBe('baseline_compare_landing')
        ->and($items->get('tenant_operations_terminal_follow_up')['destination']['kind'])->toBe('operations_index')
        ->and($items->get('tenant_operations_terminal_follow_up')['destination']['url'])->toContain('activeTab=terminal_follow_up')
        ->and($items->get('tenant_operations_terminal_follow_up')['destination']['url'])->toContain('problemClass=terminal_follow_up')
        ->and($items->get('tenant_operations_terminal_follow_up')['destination']['url'])->toContain('environment_id='.(string) $tenantOperations->getKey())
        ->and($items->get('tenant_alert_delivery_failures')['destination']['kind'])->toBe('alerts_overview')
        ->and($items->get('tenant_alert_delivery_failures')['destination']['url'])->toContain('nav%5Bback_url%5D=');
});

it('renders evidence and review actions through the shared attention-item contract', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'readonly');
    $this->actingAs($user);

    $evidenceUrl = EvidenceSnapshotResource::getUrl('index', panel: 'admin', tenant: $tenant);
    $reviewUrl = EnvironmentReviewResource::environmentScopedUrl('index', [], $tenant);

    $items = [
        [
            'key' => 'tenant_evidence_attention',
            'managed_environment_id' => (int) $tenant->getKey(),
            'tenant_label' => (string) $tenant->name,
            'tenant_route_key' => (string) $tenant->external_id,
            'family' => 'evidence',
            'urgency' => 'high',
            'title' => 'Evidence needs refresh',
            'body' => 'Current evidence should be refreshed before relying on it.',
            'supporting_message' => null,
            'badge' => 'Evidence',
            'badge_color' => 'warning',
            'destination' => [
                'kind' => 'tenant_evidence',
                'url' => $evidenceUrl,
                'tenant_route_key' => (string) $tenant->external_id,
                'label' => 'Open evidence',
                'disabled' => false,
                'helper_text' => null,
                'filters' => null,
            ],
            'action_disabled' => false,
            'helper_text' => null,
            'url' => $evidenceUrl,
        ],
        [
            'key' => 'environment_review_attention',
            'managed_environment_id' => (int) $tenant->getKey(),
            'tenant_label' => (string) $tenant->name,
            'tenant_route_key' => (string) $tenant->external_id,
            'family' => 'review',
            'urgency' => 'medium',
            'title' => 'Review needs publication work',
            'body' => 'The current review is still internal-only.',
            'supporting_message' => null,
            'badge' => 'Review',
            'badge_color' => 'warning',
            'destination' => [
                'kind' => 'environment_reviews',
                'url' => $reviewUrl,
                'tenant_route_key' => (string) $tenant->external_id,
                'label' => 'Open review',
                'disabled' => false,
                'helper_text' => null,
                'filters' => null,
            ],
            'action_disabled' => false,
            'helper_text' => null,
            'url' => $reviewUrl,
        ],
    ];

    $component = Livewire::test(WorkspaceNeedsAttention::class, [
        'items' => $items,
        'emptyState' => [],
    ])
        ->assertSee('Evidence needs refresh')
        ->assertSee('Open evidence')
        ->assertSee('Review needs publication work')
        ->assertSee('Open review');

    expect($component->html())
        ->toContain($evidenceUrl)
        ->toContain($reviewUrl);
});

it('hydrates filtered tenant-registry triage state from multi-tenant workspace backup and recovery metrics', function (): void {
    CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 9, 9, 0, 0, 'UTC'));

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

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

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

    $weakenedTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $absentTenant->workspace_id,
        'name' => 'Weakened Recovery ManagedEnvironment',
    ]);
    createUserWithTenant($weakenedTenant, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($weakenedTenant);
    $weakenedBackup = workspaceOverviewSeedHealthyBackup($weakenedTenant, [
        'completed_at' => now()->subMinutes(18),
    ]);
    workspaceOverviewSeedRestoreHistory($weakenedTenant, $weakenedBackup, 'follow_up');

    $unvalidatedTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $absentTenant->workspace_id,
        'name' => 'Unvalidated Recovery ManagedEnvironment',
    ]);
    createUserWithTenant($unvalidatedTenant, $user, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($unvalidatedTenant);
    workspaceOverviewSeedHealthyBackup($unvalidatedTenant, [
        'completed_at' => now()->subMinutes(16),
    ]);

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

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

    $this->actingAs($user);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
    Filament::setTenant(null, true);

    parse_str((string) parse_url((string) $metrics->get('backup_attention_tenants')['destination_url'], PHP_URL_QUERY), $backupQuery);

    $backupRegistry = Livewire::withQueryParams($backupQuery)
        ->actingAs($user)
        ->test(ListManagedEnvironments::class)
        ->assertSet('tableFilters.backup_posture.values', [
            'absent',
            'stale',
            'degraded',
        ])
        ->assertSet('tableFilters.triage_sort.value', TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST);

    expect($backupRegistry->instance()->getFilteredSortedTableQuery()?->pluck('managed_environments.name')->all())
        ->toBe([
            'Absent Backup ManagedEnvironment',
            'Stale Backup ManagedEnvironment',
            'Degraded Backup ManagedEnvironment',
        ]);

    parse_str((string) parse_url((string) $metrics->get('recovery_attention_tenants')['destination_url'], PHP_URL_QUERY), $recoveryQuery);

    $recoveryRegistry = Livewire::withQueryParams($recoveryQuery)
        ->actingAs($user)
        ->test(ListManagedEnvironments::class)
        ->assertSet('tableFilters.recovery_evidence.values', [
            'weakened',
            'unvalidated',
        ])
        ->assertSet('tableFilters.triage_sort.value', TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST);

    expect($recoveryRegistry->instance()->getFilteredSortedTableQuery()?->pluck('managed_environments.name')->all())
        ->toBe([
            'Absent Backup ManagedEnvironment',
            'Weakened Recovery ManagedEnvironment',
            'Unvalidated Recovery ManagedEnvironment',
        ]);
});

it('routes backup and recovery workspace attention into tenant dashboards that still show the same weakness', function (): void {
    $backupTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'name' => 'Backup Weak ManagedEnvironment',
    ]);
    [$user, $backupTenant] = createUserWithTenant($backupTenant, role: 'owner', workspaceRole: 'readonly');
    workspaceOverviewSeedQuietTenantTruth($backupTenant);

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

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

    $backupDestination = $items->get('tenant_backup_absent')['destination'];
    $recoveryDestination = $items->get('tenant_recovery_weakened')['destination'];

    expect($backupDestination['kind'])->toBe('tenant_dashboard')
        ->and($recoveryDestination['kind'])->toBe('tenant_dashboard');

    $this->actingAs($user);

    setAdminPanelContext($backupTenant);
    Livewire::test(TenantNeedsAttention::class)
        ->assertSee('No usable backup basis');

    setAdminPanelContext($recoveryTenant);
    Livewire::test(TenantNeedsAttention::class)
        ->assertSee('Recent restore needs follow-up');
});
