<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Widgets\Dashboard\RecoveryReadiness;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\Finding;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilder;
use App\Support\EnvironmentDashboard\EnvironmentDashboardSummaryBuilder;
use App\Support\Links\RequiredPermissionsLinks;
use Filament\Facades\Filament;
use Livewire\Livewire;

use function Pest\Laravel\mock;

function mockEnvironmentDashboardReadinessPermissions(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 recovery-readiness seam as a productization baseline', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $backupSet = BackupSet::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'name' => 'Productization baseline backup',
        'item_count' => 1,
        'completed_at' => now()->subMinutes(15),
    ]);

    BackupItem::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'backup_set_id' => (int) $backupSet->getKey(),
        'payload' => ['id' => 'baseline-policy'],
        'metadata' => [],
        'assignments' => [],
    ]);

    $this->actingAs($user);
    Filament::setTenant($tenant, true);

    Livewire::test(RecoveryReadiness::class)
        ->assertSee('Backup posture')
        ->assertSee('Healthy');
});

it('surfaces customer-safe output honestly when evidence exists but no review pack is ready', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    seedEnvironmentReviewEvidence($tenant);

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

    $outputCard = collect($summary['readinessCards'])->firstWhere('key', 'customer_safe_output');

    expect($outputCard)
        ->not->toBeNull()
        ->and($outputCard['status'])->toBe('Evidence available')
        ->and($outputCard['actionLabel'])->toBe('View export artifacts')
        ->and($outputCard['actionUrl'])->toBe(CustomerReviewWorkspace::environmentFilterUrl($tenant));
});

it('links ready customer-safe output directly to the latest review pack', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    $snapshot = seedEnvironmentReviewEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $pack = ReviewPack::factory()->ready()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'environment_review_id' => (int) $review->getKey(),
        'evidence_snapshot_id' => (int) $snapshot->getKey(),
    ]);

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

    $outputCard = collect($summary['readinessCards'])->firstWhere('key', 'customer_safe_output');

    expect($outputCard)
        ->not->toBeNull()
        ->and($outputCard['actionLabel'])->toBe('Open review pack')
        ->and($outputCard['actionUrl'])->toBe(ReviewPackResource::getUrl('view', ['record' => $pack], panel: 'admin', tenant: $tenant))
        ->and($outputCard['helperText'])->toBeNull();
});

it('uses required-permissions truth for provider blockage readiness summaries', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions([
        'overall' => 'blocked',
        'counts' => [
            'missing_application' => 2,
            'missing_delegated' => 1,
        ],
        'freshness' => [
            'is_stale' => true,
        ],
    ]);

    ProviderConnection::factory()->platform()->consentGranted()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'is_default' => true,
        'verification_status' => 'blocked',
        'last_health_check_at' => now()->subMinutes(12),
        'display_name' => 'Microsoft Graph',
    ]);

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

    $providerPermissions = collect($summary['governanceStatus'])->firstWhere('label', 'Provider permissions');
    $providerHealth = collect($summary['readinessCards'])->firstWhere('key', 'provider_health');

    expect($providerPermissions)
        ->not->toBeNull()
        ->and($providerPermissions['value'])->toBe('Blocked')
        ->and($providerPermissions['tone'])->toBe('danger')
        ->and($providerPermissions['description'])->toContain('2 application permission(s) are still missing.')
        ->and($providerPermissions['description'])->toContain('The verification snapshot is stale.')
        ->and($providerHealth)
        ->not->toBeNull()
        ->and($providerHealth['headline'])->toBe('Microsoft Graph')
        ->and($providerHealth['status'])->toBe('Blocked')
        ->and($providerHealth['body'])->toContain('2 application permission(s) are still missing.')
        ->and(collect($providerHealth['meta'])->firstWhere('label', 'Missing permissions')['value'] ?? null)->toBe('3');
});

it('keeps readiness follow-up destinations tenant-scoped across review, evidence, output, and permissions surfaces', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    $snapshot = seedEnvironmentReviewEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);

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

    $currentReview = collect($summary['readinessCards'])->firstWhere('key', 'current_review');
    $providerHealth = collect($summary['readinessCards'])->firstWhere('key', 'provider_health');
    $outputCard = collect($summary['readinessCards'])->firstWhere('key', 'customer_safe_output');
    $evidenceCoverage = collect($summary['governanceStatus'])->firstWhere('label', 'Evidence coverage');
    $providerPermissions = collect($summary['governanceStatus'])->firstWhere('label', 'Provider permissions');

    expect($currentReview)
        ->not->toBeNull()
        ->and($currentReview['actionUrl'])->toBe(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant))
        ->and($evidenceCoverage)
        ->not->toBeNull()
        ->and($evidenceCoverage['actionUrl'])->toBe(EvidenceSnapshotResource::getUrl('view', ['record' => $snapshot], panel: 'admin', tenant: $tenant))
        ->and($outputCard)
        ->not->toBeNull()
        ->and($outputCard['actionUrl'])->toBe(CustomerReviewWorkspace::environmentFilterUrl($tenant))
        ->and($providerHealth)
        ->not->toBeNull()
        ->and($providerHealth['actionUrl'])->toBe(RequiredPermissionsLinks::requiredPermissions($tenant))
        ->and($providerPermissions)
        ->not->toBeNull()
        ->and($providerPermissions['actionUrl'])->toBe(RequiredPermissionsLinks::requiredPermissions($tenant));
});

it('surfaces current-review progress only from repo-real review summary metrics', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_RESOLVED,
        'resolved_reason' => Finding::RESOLVE_REASON_REMEDIATED,
        'resolved_at' => now(),
    ]);

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_RISK_ACCEPTED,
    ]);

    $snapshot = seedEnvironmentReviewEvidence($tenant, findingCount: 1, driftCount: 0);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);
    $reviewSummary = is_array($review->summary) ? $review->summary : [];
    $completedSections = (int) ($reviewSummary['section_state_counts']['complete'] ?? 0);
    $totalSections = max(1, (int) ($reviewSummary['section_count'] ?? 0));
    $reviewCompletionLabel = sprintf(
        '%d/%d (%d%%)',
        $completedSections,
        $totalSections,
        (int) round(($completedSections / $totalSections) * 100),
    );

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

    $currentReview = collect($summary['readinessCards'])->firstWhere('key', 'current_review');
    $progress = collect($currentReview['progress'] ?? []);

    expect($currentReview)
        ->not->toBeNull()
        ->and($progress)->toHaveCount(2)
        ->and($progress->pluck('key')->all())->toBe(['findings_with_outcome', 'review_completion'])
        ->and($progress->pluck('key')->contains('evidence_attachment'))->toBeFalse()
        ->and($progress->firstWhere('key', 'findings_with_outcome')['valueLabel'] ?? null)->toBe('2/3 (67%)')
        ->and($progress->firstWhere('key', 'review_completion')['valueLabel'] ?? null)->toBe($reviewCompletionLabel);
});

it('renders current-review progress bars with a fixed visible track height and filament tone colors', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_RESOLVED,
        'resolved_reason' => Finding::RESOLVE_REASON_REMEDIATED,
        'resolved_at' => now(),
    ]);

    Finding::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_RISK_ACCEPTED,
    ]);

    $snapshot = seedEnvironmentReviewEvidence($tenant, findingCount: 1, driftCount: 0);
    composeEnvironmentReviewForTest($tenant, $user, $snapshot);

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

    $content = $this->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $tenant))
        ->assertSuccessful()
        ->getContent();

    expect(substr_count($content, 'role="progressbar"'))->toBeGreaterThanOrEqual(2)
        ->and($content)->toContain('style="height: 0.5rem;"')
        ->and($content)->toContain('background-color: var(--primary-500);')
        ->and($content)->toContain('background-color: var(--warning-500);');
});

it('omits current-review progress bars when the review summary has no real denominators', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

    $snapshot = seedEnvironmentReviewEvidence($tenant);
    $review = composeEnvironmentReviewForTest($tenant, $user, $snapshot);

    $review->forceFill([
        'summary' => [],
    ])->save();

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

    $currentReview = collect($summary['readinessCards'])->firstWhere('key', 'current_review');

    expect($currentReview)
        ->not->toBeNull()
        ->and($currentReview['progress'] ?? null)->toBe([]);
});

it('shows honest fallback states when review and evidence artifacts are not available yet', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    mockEnvironmentDashboardReadinessPermissions();

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

    $currentReview = collect($summary['readinessCards'])->firstWhere('key', 'current_review');
    $providerHealth = collect($summary['readinessCards'])->firstWhere('key', 'provider_health');
    $outputCard = collect($summary['readinessCards'])->firstWhere('key', 'customer_safe_output');
    $evidenceCoverage = collect($summary['governanceStatus'])->firstWhere('label', 'Evidence coverage');

    expect($currentReview)
        ->not->toBeNull()
        ->and($currentReview['status'])->toBe('No active review')
        ->and($currentReview['body'])->toBe('There is currently no review in progress for this environment.')
        ->and($currentReview['actionUrl'])->toBe(EnvironmentReviewResource::environmentScopedUrl('index', tenant: $tenant))
        ->and($providerHealth)
        ->not->toBeNull()
        ->and($providerHealth['status'])->toBe('Provider status unavailable')
        ->and($providerHealth['body'])->toBe('No provider health snapshot is currently available for this environment.')
        ->and($providerHealth['actionUrl'])->toBe(RequiredPermissionsLinks::requiredPermissions($tenant))
        ->and($outputCard)
        ->not->toBeNull()
        ->and($outputCard['status'])->toBe('No customer-safe output available')
        ->and($outputCard['body'])->toBe('Generate a review pack once review and evidence are ready for handoff.')
        ->and($outputCard['actionLabel'])->toBe('View export artifacts')
        ->and($outputCard['actionUrl'])->toBe(CustomerReviewWorkspace::environmentFilterUrl($tenant))
        ->and($evidenceCoverage)
        ->not->toBeNull()
        ->and($evidenceCoverage['value'])->toBe('Unavailable')
        ->and($evidenceCoverage['description'])->toBe('No evidence snapshot is currently available for customer-safe output.')
        ->and($evidenceCoverage['actionUrl'])->toBe(EvidenceSnapshotResource::getUrl('index', panel: 'admin', tenant: $tenant));
});
