<?php

declare(strict_types=1);

use App\Models\ManagedEnvironment;
use App\Support\Links\RequiredPermissionsLinks;
use App\Support\OperationRunOutcome;
use App\Support\ProductKnowledge\ContextualHelpCatalog;
use App\Support\ProductKnowledge\ContextualHelpResolver;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

function contextualHelpTruthEnvelope(ManagedEnvironment $tenant): ArtifactTruthEnvelope
{
    return new ArtifactTruthEnvelope(
        artifactFamily: 'support_diagnostics',
        artifactKey: 'tenant_support_diagnostics',
        workspaceId: (int) $tenant->workspace_id,
        tenantId: (int) $tenant->getKey(),
        executionOutcome: 'blocked',
        artifactExistence: 'created',
        contentState: 'partial',
        freshnessState: 'current',
        publicationReadiness: null,
        supportState: 'supported',
        actionability: 'required',
        primaryLabel: 'Verification blocked',
        primaryExplanation: 'Verification cannot continue until the prerequisite is resolved.',
        diagnosticLabel: 'Admin consent required',
        nextActionLabel: 'Retry verification',
        nextActionUrl: null,
        relatedRunId: null,
        relatedArtifactUrl: null,
    );
}

it('resolves contextual help with reason translation, operator summary, and tenant-aware links', function (): void {
    [, $tenant] = createUserWithTenant(ensureDefaultMicrosoftProviderConnection: false);

    $payload = app(ContextualHelpResolver::class)->resolve(ContextualHelpCatalog::ADMIN_CONSENT_REQUIRED, [
        'tenant' => $tenant,
        'reason_code' => ProviderReasonCodes::ProviderConsentMissing,
        'artifact_truth' => contextualHelpTruthEnvelope($tenant),
    ]);

    expect($payload)->toMatchArray([
        'topic_key' => ContextualHelpCatalog::ADMIN_CONSENT_REQUIRED,
        'headline' => 'Admin consent required',
        'short_explanation' => 'The provider connection cannot continue until admin consent is granted.',
        'safe_next_action' => 'Retry verification',
        'reason_label' => 'Admin consent required',
        'diagnostic_code' => ProviderReasonCodes::ProviderConsentMissing,
    ])->and($payload['docs_links'][0])->toMatchArray([
        'label' => 'Grant admin consent',
        'resolver' => ContextualHelpCatalog::LINK_RESOLVER_ADMIN_CONSENT_PRIMARY,
        'url' => RequiredPermissionsLinks::adminConsentGuideUrl(),
    ])->and($payload['operator_summary'])->toMatchArray([
        'nextActionText' => 'Retry verification',
        'diagnosticsAvailable' => true,
    ]);
});

it('resolves required permissions links against the current tenant', function (): void {
    [, $tenant] = createUserWithTenant(ensureDefaultMicrosoftProviderConnection: false);

    $payload = app(ContextualHelpResolver::class)->resolve(ContextualHelpCatalog::REQUIRED_PERMISSIONS_MISSING, [
        'tenant' => $tenant,
    ]);

    expect($payload['docs_links'][0])->toMatchArray([
        'label' => 'Open required permissions',
        'resolver' => ContextualHelpCatalog::LINK_RESOLVER_REQUIRED_PERMISSIONS,
        'url' => RequiredPermissionsLinks::requiredPermissions($tenant),
    ]);
});

it('maps support diagnostics topics from shared reason and outcome signals', function (): void {
    $resolver = app(ContextualHelpResolver::class);

    expect($resolver->topicKeyForSupportDiagnostics(
        reasonCode: ProviderReasonCodes::RateLimited,
        hasIncompleteEvidence: false,
        runOutcome: null,
    ))->toBe(ContextualHelpCatalog::RETRYABLE_PROVIDER_FAILURE)
        ->and($resolver->topicKeyForSupportDiagnostics(
            reasonCode: ProviderReasonCodes::UnknownError,
            hasIncompleteEvidence: false,
            runOutcome: OperationRunOutcome::Failed->value,
        ))->toBe(ContextualHelpCatalog::MANUAL_HANDOFF_REQUIRED)
        ->and($resolver->topicKeyForSupportDiagnostics(
            reasonCode: null,
            hasIncompleteEvidence: false,
            runOutcome: OperationRunOutcome::Failed->value,
        ))->toBe(ContextualHelpCatalog::VERIFICATION_FAILED)
        ->and($resolver->topicKeyForSupportDiagnostics(
            reasonCode: null,
            hasIncompleteEvidence: true,
            runOutcome: null,
        ))->toBe(ContextualHelpCatalog::DIAGNOSTIC_EVIDENCE_INCOMPLETE);
});
