<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Filament\Resources\RestoreRunResource;
use App\Models\ManagedEnvironment;
use App\Services\Auth\CapabilityResolver;
use App\Support\Auth\Capabilities;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\Rbac\UiTooltips;
use App\Support\RestoreSafety\RestoreResultAttention;
use App\Support\Tenants\TenantRecoveryTriagePresentation;
use Tests\Feature\Concerns\BuildsPortfolioTriageFixtures;

use function Pest\Laravel\mock;

uses(BuildsPortfolioTriageFixtures::class);

function tenantDashboardVisibilityArrivalUrl(\App\Models\ManagedEnvironment $tenant): string
{
    return EnvironmentDashboard::getUrl([
        PortfolioArrivalContextToken::QUERY_PARAMETER => PortfolioArrivalContextToken::encode([
            'sourceSurface' => PortfolioArrivalContextToken::SOURCE_TENANT_REGISTRY,
            'tenantRouteKey' => (string) $tenant->external_id,
            'workspaceId' => (int) $tenant->workspace_id,
            'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
            'concernState' => TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED,
            'concernReason' => RestoreResultAttention::STATE_FAILED,
            'returnFilters' => [
                'recovery_evidence' => [TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED],
                'triage_sort' => TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
            ],
        ]),
    ], panel: 'admin', tenant: $tenant);
}

it('shows an actionable follow-up link for in-scope members who can open the target surface', function (): void {
    [$user, $tenant] = $this->makePortfolioTriageActor('Visible Arrival ManagedEnvironment', role: 'readonly');
    $restoreRun = $this->seedPortfolioRecoveryConcern($tenant, RestoreResultAttention::STATE_FAILED);
    $this->actingAs($user);

    $this->get(tenantDashboardVisibilityArrivalUrl($tenant))
        ->assertOk()
        ->assertSee('Triage arrival')
        ->assertSee('Open restore run')
        ->assertSee('Return to tenant triage');

    $this->get(RestoreRunResource::getUrl('view', [
        'record' => (int) $restoreRun->getKey(),
        'recovery_posture_reason' => RestoreResultAttention::STATE_FAILED,
    ], panel: 'admin', tenant: $tenant))
        ->assertOk();
});

it('keeps the arrival block truthful while degrading the CTA for in-scope members without follow-up capability', function (): void {
    [$user, $tenant] = $this->makePortfolioTriageActor('Restricted Arrival ManagedEnvironment');
    $restoreRun = $this->seedPortfolioRecoveryConcern($tenant, RestoreResultAttention::STATE_FAILED);
    $this->actingAs($user);

    mock(CapabilityResolver::class, function ($mock) use ($tenant): void {
        $mock->shouldReceive('primeMemberships')
            ->zeroOrMoreTimes();

        $mock->shouldReceive('isMember')
            ->andReturnUsing(static fn ($user, $resolvedTenant): bool => (int) $resolvedTenant->getKey() === (int) $tenant->getKey());

        $mock->shouldReceive('can')
            ->andReturnUsing(static function ($user, $resolvedTenant, string $capability) use ($tenant): bool {
                expect((int) $resolvedTenant->getKey())->toBe((int) $tenant->getKey());

                return $capability !== Capabilities::TENANT_VIEW;
            });
    });

    $this->get(tenantDashboardVisibilityArrivalUrl($tenant))
        ->assertOk()
        ->assertSee('Triage arrival')
        ->assertSee(UiTooltips::INSUFFICIENT_PERMISSION)
        ->assertDontSee('href="'.e(RestoreRunResource::getUrl('view', [
            'record' => (int) $restoreRun->getKey(),
            'recovery_posture_reason' => RestoreResultAttention::STATE_FAILED,
        ], panel: 'admin', tenant: $tenant)).'"', false);

    $this->get(RestoreRunResource::getUrl('view', [
        'record' => (int) $restoreRun->getKey(),
        'recovery_posture_reason' => RestoreResultAttention::STATE_FAILED,
    ], panel: 'admin', tenant: $tenant))
        ->assertForbidden();
});

it('keeps tenant-dashboard arrival routes deny-as-not-found for non-members', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    [$user] = $this->makePortfolioTriageActor('Other ManagedEnvironment');
    $this->seedPortfolioRecoveryConcern($tenant, RestoreResultAttention::STATE_FAILED);
    $this->actingAs($user);

    $this->get(tenantDashboardVisibilityArrivalUrl($tenant))
        ->assertNotFound();
});
