<?php

declare(strict_types=1);

use App\Filament\Pages\Governance\GovernanceInbox;
use App\Models\AlertDelivery;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentTriageReview;
use App\Models\OperationRun;
use App\Support\BackupHealth\TenantBackupHealthResolver;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\PortfolioTriage\ManagedEnvironmentTriageReviewFingerprint;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\Workspaces\WorkspaceContext;

it('renders visible governance attention sections on the governance inbox page', function (): void {
    $alphaTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'name' => 'Alpha ManagedEnvironment',
        'external_id' => 'alpha-tenant',
    ]);
    [$user, $alphaTenant] = createUserWithTenant($alphaTenant, role: 'owner', workspaceRole: 'owner');

    $bravoTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $alphaTenant->workspace_id,
        'name' => 'Bravo ManagedEnvironment',
        'external_id' => 'bravo-tenant',
    ]);

    $user->tenants()->syncWithoutDetaching([
        (int) $bravoTenant->getKey() => ['role' => 'owner'],
    ]);

    Finding::factory()
        ->for($alphaTenant)
        ->assignedTo((int) $user->getKey())
        ->ownedBy((int) $user->getKey())
        ->overdueByHours()
        ->create();

    Finding::factory()
        ->for($bravoTenant)
        ->reopened()
        ->create();

    $exceptionFinding = Finding::factory()
        ->for($alphaTenant)
        ->riskAccepted()
        ->create([
            'workspace_id' => (int) $alphaTenant->workspace_id,
            'subject_external_id' => 'exception-governance-home',
        ]);

    FindingException::query()->create([
        'workspace_id' => (int) $alphaTenant->workspace_id,
        'managed_environment_id' => (int) $alphaTenant->getKey(),
        'finding_id' => (int) $exceptionFinding->getKey(),
        'requested_by_user_id' => (int) $user->getKey(),
        'owner_user_id' => (int) $user->getKey(),
        'status' => FindingException::STATUS_PENDING,
        'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
        'request_reason' => 'Governance home exception review',
        'requested_at' => now()->subDay(),
        'review_due_at' => now()->addDay(),
        'evidence_summary' => ['reference_count' => 0],
    ]);

    OperationRun::factory()
        ->forTenant($alphaTenant)
        ->create([
            'status' => OperationRunStatus::Completed->value,
            'outcome' => OperationRunOutcome::Failed->value,
            'completed_at' => now()->subMinute(),
        ]);

    AlertDelivery::factory()->create([
        'managed_environment_id' => null,
        'workspace_id' => (int) $alphaTenant->workspace_id,
        'status' => AlertDelivery::STATUS_FAILED,
        'payload' => [
            'title' => 'Delivery failed',
            'body' => 'A notification destination failed.',
        ],
    ]);

    $backupHealthResolver = app(TenantBackupHealthResolver::class);
    $fingerprints = app(ManagedEnvironmentTriageReviewFingerprint::class);
    $alphaBackupFingerprint = $fingerprints->forBackupHealth($backupHealthResolver->assess($alphaTenant));

    expect($alphaBackupFingerprint)->not->toBeNull();

    ManagedEnvironmentTriageReview::factory()
        ->for($alphaTenant)
        ->followUpNeeded()
        ->create([
            'workspace_id' => (int) $alphaTenant->workspace_id,
            'reviewed_by_user_id' => (int) $user->getKey(),
            'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
            'review_fingerprint' => $alphaBackupFingerprint['fingerprint'],
            'review_snapshot' => $alphaBackupFingerprint['snapshot'],
        ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id])
        ->get(GovernanceInbox::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertSee('Assigned findings')
        ->assertSee('Findings intake')
        ->assertSee('Finding exceptions')
        ->assertSee('Operations follow-up')
        ->assertSee('Alert delivery failures')
        ->assertSee('Review follow-up')
        ->assertSee('Open my findings')
        ->assertSee('Open finding exceptions')
        ->assertSee('Open terminal follow-up')
        ->assertSee('Open alert deliveries')
        ->assertSee('Open customer review workspace');
});

it('renders honest empty states for tenant and family filtering on the governance inbox page', function (): void {
    $alphaTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'name' => 'Alpha ManagedEnvironment',
        'external_id' => 'alpha-tenant',
    ]);
    [$user, $alphaTenant] = createUserWithTenant($alphaTenant, role: 'owner', workspaceRole: 'owner');

    $bravoTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $alphaTenant->workspace_id,
        'name' => 'Bravo ManagedEnvironment',
        'external_id' => 'bravo-tenant',
    ]);

    $user->tenants()->syncWithoutDetaching([
        (int) $bravoTenant->getKey() => ['role' => 'owner'],
    ]);

    Finding::factory()
        ->for($bravoTenant)
        ->assignedTo((int) $user->getKey())
        ->create();

    AlertDelivery::factory()->create([
        'managed_environment_id' => null,
        'workspace_id' => (int) $alphaTenant->workspace_id,
        'status' => AlertDelivery::STATUS_FAILED,
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id])
        ->get(GovernanceInbox::getUrl(panel: 'admin').'?environment_id='.(string) $alphaTenant->getKey())
        ->assertOk()
        ->assertSee('This environment filter is hiding other visible attention')
        ->assertSee('Clear environment filter');

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $alphaTenant->workspace_id])
        ->get(GovernanceInbox::getUrl(panel: 'admin').'?environment_id='.(string) $alphaTenant->getKey().'&family=alert_delivery_failures')
        ->assertOk()
        ->assertSee('Alert delivery failures')
        ->assertSee('No failed alert deliveries match this environment filter right now.')
        ->assertDontSee('Open my findings');
});

it('omits the finding exceptions lane when the workspace capability is not visible', function (): void {
    $tenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'name' => 'Alpha ManagedEnvironment',
    ]);
    [$user, $tenant] = createUserWithTenant($tenant, role: 'owner', workspaceRole: 'readonly');

    Finding::factory()
        ->for($tenant)
        ->assignedTo((int) $user->getKey())
        ->create([
            'workspace_id' => (int) $tenant->workspace_id,
        ]);

    $exceptionFinding = Finding::factory()
        ->for($tenant)
        ->riskAccepted()
        ->create([
            'workspace_id' => (int) $tenant->workspace_id,
        ]);

    FindingException::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'finding_id' => (int) $exceptionFinding->getKey(),
        'requested_by_user_id' => (int) $user->getKey(),
        'owner_user_id' => (int) $user->getKey(),
        'status' => FindingException::STATUS_PENDING,
        'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
        'request_reason' => 'Hidden exception lane',
        'requested_at' => now()->subDay(),
        'review_due_at' => now()->addDay(),
        'evidence_summary' => ['reference_count' => 0],
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(GovernanceInbox::getUrl(panel: 'admin'))
        ->assertOk()
        ->assertSee('Assigned findings')
        ->assertDontSee('Finding exceptions')
        ->assertDontSee('Hidden exception lane');
});
