<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Models\Finding;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilder;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\EnvironmentDashboard\EnvironmentDashboardSummaryBuilder;
use Illuminate\Support\Carbon;

use function Pest\Laravel\mock;

function mockEnvironmentDashboardSummaryPermissions(array $overview = []): void
{
    mock(ManagedEnvironmentRequiredPermissionsViewModelBuilder::class, function ($mock) use ($overview): void {
        $mock->shouldReceive('build')->andReturn([
            'overview' => array_replace_recursive([
                'overall' => 'ready',
                'counts' => [
                    'missing_application' => 0,
                    'missing_delegated' => 0,
                ],
                'freshness' => [
                    'is_stale' => false,
                    'last_refreshed_at' => now()->toIso8601String(),
                ],
            ], $overview),
        ]);
    });
}

it('renders the decision-first tenant overview with the capped first-screen structure', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardSummaryPermissions();

    [$profile, $snapshot] = seedActiveBaselineForTenant($tenant);

    seedBaselineCompareRun($tenant, $profile, $snapshot, workspaceOverviewCompareCoverage());

    $backupSet = workspaceOverviewSeedHealthyBackup($tenant);

    workspaceOverviewSeedRestoreHistory($tenant, $backupSet);

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'finding_type' => Finding::FINDING_TYPE_DRIFT,
        'severity' => Finding::SEVERITY_HIGH,
        'status' => Finding::STATUS_NEW,
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'completed_at' => now()->subHour(),
    ]);

    ProviderConnection::factory()->platform()->consentGranted()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'is_default' => true,
    ]);

    $this->actingAs($user);
    setAdminEnvironmentContext($tenant);

    $response = $this->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant))
        ->assertSuccessful()
        ->assertSee($tenant->name)
        ->assertSee('Recommended next actions')
        ->assertSee('Governance status')
        ->assertSee('Operations needing attention')
        ->assertSee('Current review')
        ->assertSee('Risk exceptions')
        ->assertSee('Provider Health')
        ->assertSee('Customer-safe output')
        ->assertSee('Operations requiring attention')
        ->assertSee('Review operation')
        ->assertSee('Open operations hub')
        ->assertDontSee('Recent operations');

    $content = $response->getContent();
    $contextChipsPosition = strpos($content, 'data-testid="tenant-dashboard-context-chips"');
    $firstKpiPosition = strpos($content, 'data-testid="tenant-dashboard-kpi"');
    $governanceStatusCount = substr_count($content, 'data-testid="tenant-dashboard-governance-status"');
    $secondaryListRowCount = substr_count($content, 'data-overview-row-style="secondary-list-row"');

    expect(substr_count($content, 'data-testid="tenant-dashboard-kpi"'))->toBe(4)
        ->and($content)->toContain('data-testid="tenant-dashboard-posture-pill"')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chips"')
        ->and($content)->toContain('class="flex w-full flex-col items-start gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-start md:flex-nowrap"')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-workspace"')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-workspace" class="inline-flex min-w-0 w-full max-w-full items-center')
        ->and($content)->toContain('sm:w-auto sm:max-w-[20rem] lg:max-w-[24rem]')
        ->and($content)->toContain('Workspace: '.$tenant->workspace->name)
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-provider"')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-provider-microsoft-logo"')
        ->and($content)->toContain('data-provider-key="microsoft"')
        ->and($content)->toContain('Microsoft environment')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-latest-activity" class="inline-flex items-center gap-2 whitespace-nowrap')
        ->and($content)->toContain('data-testid="tenant-dashboard-context-chip-latest-activity-icon"')
        ->and($content)->toContain('Latest activity:')
        ->and($contextChipsPosition)->not->toBeFalse()
        ->and($firstKpiPosition)->not->toBeFalse()
        ->and($contextChipsPosition)->toBeLessThan($firstKpiPosition)
        ->and($secondaryListRowCount)->toBe($governanceStatusCount)
        ->and($content)->toContain('hover:shadow-md')
        ->and($content)->toContain('hover:ring-1')
        ->and(substr_count($content, 'data-kpi-has-icon="true"'))->toBe(4)
        ->and(substr_count($content, 'data-kpi-has-chart="true"'))->toBe(2)
        ->and(substr_count($content, 'data-testid="tenant-dashboard-recommended-action"'))->toBeLessThanOrEqual(3)
        ->and(substr_count($content, 'tenant-dashboard-recommended-actions'))->toBeGreaterThanOrEqual(1)
        ->and(substr_count($content, 'data-testid="tenant-dashboard-governance-status-icon"'))->toBe(substr_count($content, 'data-testid="tenant-dashboard-governance-status"'))
        ->and(substr_count($content, 'data-testid="tenant-dashboard-operations-attention-item-icon"'))->toBeGreaterThanOrEqual(1)
        ->and(substr_count($content, 'data-testid="tenant-dashboard-readiness-card"'))->toBe(4)
        ->and($content)->toContain('data-readiness-key="provider_health"')
        ->and($content)->not->toContain('Open customer workspace')
        ->and($content)->not->toContain('fixed bottom-4 right-4 z-[999999] w-96 space-y-2')
        ->and($content)->toContain('High severity findings')
        ->and($content)->not->toContain('section_recent_operations');
});

it('adds repo-real icon metadata and only supported sparkline series to tenant dashboard kpis', function (): void {
    Carbon::setTestNow('2026-05-03 12:00:00');

    try {
        [$user, $tenant] = createUserWithTenant(role: 'owner');

        mockEnvironmentDashboardSummaryPermissions([
            'counts' => [
                'missing_application' => 2,
                'missing_delegated' => 1,
            ],
        ]);

        [$profile, $snapshot] = seedActiveBaselineForTenant($tenant);

        seedBaselineCompareRun($tenant, $profile, $snapshot, workspaceOverviewCompareCoverage());

        $backupSet = workspaceOverviewSeedHealthyBackup($tenant);

        workspaceOverviewSeedRestoreHistory($tenant, $backupSet);

        foreach ([6, 6, 4, 1] as $daysAgo) {
            Finding::factory()->create([
                'managed_environment_id' => (int) $tenant->getKey(),
                'workspace_id' => (int) $tenant->workspace_id,
                'finding_type' => Finding::FINDING_TYPE_DRIFT,
                'severity' => $daysAgo === 4 ? Finding::SEVERITY_CRITICAL : Finding::SEVERITY_HIGH,
                'status' => Finding::STATUS_NEW,
                'first_seen_at' => now()->subDays($daysAgo),
                'last_seen_at' => now()->subDays($daysAgo),
            ]);
        }

        Finding::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'workspace_id' => (int) $tenant->workspace_id,
            'finding_type' => Finding::FINDING_TYPE_DRIFT,
            'severity' => Finding::SEVERITY_MEDIUM,
            'status' => Finding::STATUS_NEW,
            'first_seen_at' => now()->subDays(2),
            'last_seen_at' => now()->subDays(2),
        ]);

        Finding::factory()->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'workspace_id' => (int) $tenant->workspace_id,
            'finding_type' => Finding::FINDING_TYPE_DRIFT,
            'severity' => Finding::SEVERITY_MEDIUM,
            'status' => Finding::STATUS_NEW,
            'first_seen_at' => now()->subDays(2),
            'last_seen_at' => now()->subDays(2),
            'due_at' => now()->subDay(),
        ]);

        foreach ([5, 2, 2] as $daysAgo) {
            OperationRun::factory()->create([
                'managed_environment_id' => (int) $tenant->getKey(),
                'workspace_id' => (int) $tenant->workspace_id,
                'type' => 'inventory_sync',
                'status' => OperationRunStatus::Completed->value,
                'outcome' => OperationRunOutcome::Failed->value,
                'created_at' => now()->subDays($daysAgo)->subHours(3),
                'completed_at' => now()->subDays($daysAgo),
            ]);
        }

        $kpis = collect(app(EnvironmentDashboardSummaryBuilder::class)
            ->build($tenant, $user)
            ->toArray()['kpis'])
            ->keyBy('key');

        expect($kpis->keys()->all())->toBe([
            'high_severity_findings',
            'overdue_findings',
            'missing_permissions',
            'active_operations',
        ])
            ->and($kpis['active_operations']['label'])->toBe('Operations needing attention')
            ->and($kpis->pluck('icon')->filter()->count())->toBe(4)
            ->and($kpis['high_severity_findings']['icon'])->toBe('heroicon-m-arrow-trending-up')
            ->and($kpis['high_severity_findings']['description'])->toBe('4 active · 4 new in 7d')
            ->and($kpis['high_severity_findings']['chart'])->toBe([2, 0, 1, 0, 0, 1, 0])
            ->and($kpis['overdue_findings']['icon'])->toBe('heroicon-m-arrow-trending-up')
            ->and($kpis['overdue_findings']['description'])->toBe('1 overdue now')
            ->and($kpis['missing_permissions']['icon'])->toBe('heroicon-m-arrow-trending-up')
            ->and($kpis['missing_permissions']['description'])->toBe('2 app · 1 delegated missing')
            ->and($kpis['active_operations']['icon'])->toBe('heroicon-m-arrow-trending-up')
            ->and($kpis['active_operations']['description'])->toBe('3 operations require attention')
            ->and($kpis['active_operations']['chart'])->toBe([0, 1, 0, 0, 2, 0, 0])
            ->and($kpis['overdue_findings']['chart'])->toBeNull()
            ->and($kpis['missing_permissions']['chart'])->toBeNull();
    } finally {
        Carbon::setTestNow();
    }
});

it('adds semantic icon metadata to governance status rows and curated operations attention items', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardSummaryPermissions();

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'created_at' => now()->subMinutes(3),
        'completed_at' => now()->subMinutes(3),
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'environment.review_pack.generate',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'created_at' => now()->subMinutes(2),
        'completed_at' => now()->subMinutes(2),
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => OperationCatalog::TYPE_PERMISSION_POSTURE_CHECK,
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Blocked->value,
        'created_at' => now()->subMinute(),
        'completed_at' => now()->subMinute(),
    ]);

    $summary = app(EnvironmentDashboardSummaryBuilder::class)
        ->build($tenant, $user)
        ->toArray();

    $governanceStatus = collect($summary['governanceStatus'])->keyBy('key');
    $attentionOperations = collect($summary['activeOperationSummary']['items'] ?? [])->keyBy('type');

    expect($governanceStatus['baseline_compare']['icon'] ?? null)->toBe('heroicon-m-arrows-right-left')
        ->and($governanceStatus['evidence_coverage']['icon'] ?? null)->toBe('heroicon-m-document-check')
        ->and($governanceStatus['review_freshness']['icon'] ?? null)->toBe('heroicon-m-clipboard-document-check')
        ->and($governanceStatus['provider_permissions']['icon'] ?? null)->toBe('heroicon-m-key')
        ->and($governanceStatus['backup_posture']['icon'] ?? null)->toBe('heroicon-m-archive-box')
        ->and($attentionOperations['Inventory sync']['icon'] ?? null)->toBe('heroicon-m-arrow-path')
        ->and($attentionOperations['Review pack generation']['icon'] ?? null)->toBe('heroicon-m-document-arrow-down')
        ->and($attentionOperations['Permission posture check']['icon'] ?? null)->toBe('heroicon-m-key');
});

it('shows calm honest fallbacks when no urgent tenant follow-up is visible', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardSummaryPermissions();

    [$profile, $snapshot] = seedActiveBaselineForTenant($tenant);

    seedBaselineCompareRun($tenant, $profile, $snapshot, workspaceOverviewCompareCoverage());

    $backupSet = workspaceOverviewSeedHealthyBackup($tenant);

    workspaceOverviewSeedRestoreHistory($tenant, $backupSet);

    $this->actingAs($user);
    setAdminEnvironmentContext($tenant);

    $response = $this->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant))
        ->assertSuccessful()
        ->assertSee('No immediate action is waiting.')
        ->assertDontSee('Recent operations')
        ->assertDontSee('Operations requiring attention');

    $content = $response->getContent();

    expect(substr_count($content, 'data-testid="tenant-dashboard-recommended-actions-empty"'))->toBe(1)
        ->and($content)->not->toContain('data-testid="tenant-dashboard-operations-attention-summary"')
        ->and($content)->not->toContain('data-testid="tenant-dashboard-recent-operations-empty"');
});

it('builds a curated operations requiring attention summary and excludes healthy active runs', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardSummaryPermissions();

    $healthyRunningRun = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => OperationRunStatus::Running->value,
        'outcome' => OperationRunOutcome::Pending->value,
        'created_at' => now()->subMinute(),
        'started_at' => now()->subMinute(),
    ]);

    $followUpRun = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Failed->value,
        'created_at' => now()->subMinutes(6),
        'started_at' => now()->subMinutes(5),
        'completed_at' => now()->subMinutes(4),
    ]);

    $blockedRun = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => OperationCatalog::TYPE_PERMISSION_POSTURE_CHECK,
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Blocked->value,
        'created_at' => now()->subMinutes(5),
        'started_at' => now()->subMinutes(4),
        'completed_at' => now()->subMinutes(3),
    ]);

    $summary = app(EnvironmentDashboardSummaryBuilder::class)
        ->build($tenant, $user)
        ->toArray();

    $activeOperationSummary = $summary['activeOperationSummary'] ?? null;
    $items = collect($activeOperationSummary['items'] ?? []);

    expect($activeOperationSummary)
        ->not->toBeNull()
        ->and($activeOperationSummary['title'] ?? null)->toBe('Operations requiring attention')
        ->and($activeOperationSummary['count'] ?? null)->toBe(2)
        ->and($activeOperationSummary['secondaryActionLabel'] ?? null)->toBe('Open operations hub')
        ->and($activeOperationSummary['secondaryActionUrl'] ?? null)->toBe(OperationRunLinks::index(
            $tenant,
            activeTab: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP,
            problemClass: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP,
        ))
        ->and($items)->toHaveCount(2)
        ->and($items->pluck('id')->all())->toBe([
            (int) $blockedRun->getKey(),
            (int) $followUpRun->getKey(),
        ])
        ->and($items->pluck('primaryActionLabel')->unique()->all())->toBe(['Review operation'])
        ->and($items->pluck('primaryActionUrl')->all())->toBe([
            OperationRunLinks::view($blockedRun, $tenant),
            OperationRunLinks::view($followUpRun, $tenant),
        ])
        ->and($items->pluck('attentionLabel')->unique()->all())->toBe(['Follow-up required'])
        ->and($items->pluck('timingLabel')->filter()->isNotEmpty())->toBeTrue()
        ->and($items->pluck('outcomeSentence')->filter()->isNotEmpty())->toBeTrue()
        ->and($items->pluck('reason')->filter()->isNotEmpty())->toBeTrue()
        ->and($items->pluck('impact')->filter()->isNotEmpty())->toBeTrue()
        ->and($items->pluck('id')->contains((int) $healthyRunningRun->getKey()))->toBeFalse();

    $this->actingAs($user);
    setAdminEnvironmentContext($tenant);

    $this->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant))
        ->assertSuccessful()
        ->assertSee('data-testid="tenant-dashboard-operations-attention-summary"', false)
        ->assertSee('Review operation')
        ->assertSee('Open operations hub')
        ->assertSee('Completed '.$followUpRun->completed_at?->diffForHumans())
        ->assertSee('Inventory sync')
        ->assertDontSee('Operation #'.$followUpRun->getKey())
        ->assertDontSee('Recent operations');
});

it('omits the compact active operations summary when no qualifying visible run exists', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardSummaryPermissions();

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Succeeded->value,
        'created_at' => now()->subMinutes(3),
        'started_at' => now()->subMinutes(2),
        'completed_at' => now()->subMinute(),
    ]);

    $summary = app(EnvironmentDashboardSummaryBuilder::class)
        ->build($tenant, $user)
        ->toArray();

    expect($summary['activeOperationSummary'] ?? null)->toBeNull();

    $this->actingAs($user);
    setAdminEnvironmentContext($tenant);

    $this->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant))
        ->assertSuccessful()
        ->assertDontSee('data-testid="tenant-dashboard-operations-attention-summary"', false)
        ->assertDontSee('Review operation')
        ->assertDontSee('Open operations hub')
        ->assertDontSee('Recent operations');
});
