<?php

use App\Support\Providers\Boundary\ProviderBoundaryCatalog;
use App\Support\Providers\Boundary\ProviderBoundaryOwner;
use App\Support\Providers\Boundary\ProviderBoundarySeam;

it('classifies the authoritative first-slice provider seams', function (): void {
    $catalog = app(ProviderBoundaryCatalog::class);

    expect(array_keys($catalog->all()))->toBe([
        'provider.capability_registry',
        'provider.connection_resolution',
        'provider.gateway_runtime',
        'provider.identity_resolution',
        'provider.operation_registry',
        'provider.operation_start_gate',
    ]);

    expect($catalog->get('provider.gateway_runtime')->owner)->toBe(ProviderBoundaryOwner::ProviderOwned);
    expect($catalog->get('provider.capability_registry')->owner)->toBe(ProviderBoundaryOwner::PlatformCore);
    expect($catalog->get('provider.identity_resolution')->owner)->toBe(ProviderBoundaryOwner::PlatformCore);
    expect($catalog->get('provider.connection_resolution')->owner)->toBe(ProviderBoundaryOwner::PlatformCore);
    expect($catalog->get('provider.operation_registry')->owner)->toBe(ProviderBoundaryOwner::PlatformCore);
    expect($catalog->get('provider.operation_start_gate')->owner)->toBe(ProviderBoundaryOwner::PlatformCore);
});

it('records implementation paths and bounded exception metadata for platform-core seams', function (): void {
    $catalog = app(ProviderBoundaryCatalog::class);

    $identity = $catalog->get('provider.identity_resolution');

    expect($identity->coversPath('app/Services/Providers/ProviderIdentityResolution.php'))->toBeTrue()
        ->and($identity->neutralTerms)->toContain('target scope')
        ->and($identity->retainedProviderSemantics)->toContain('provider_context.microsoft_tenant_id')
        ->and($identity->retainedProviderSemantics)->not->toContain('Microsoft Graph option keys')
        ->and($identity->followUpAction)->toBe(ProviderBoundarySeam::FOLLOW_UP_DOCUMENT_IN_FEATURE);

    $registry = $catalog->get('provider.operation_registry');

    expect($registry->neutralTerms)->toContain('provider binding')
        ->and($registry->retainedProviderSemantics)->toContain('active provider binding')
        ->and($registry->followUpAction)->toBe(ProviderBoundarySeam::FOLLOW_UP_DOCUMENT_IN_FEATURE);
});

it('aligns the catalog shape with the logical boundary contract', function (): void {
    $seam = app(ProviderBoundaryCatalog::class)->get('provider.operation_start_gate');

    expect($seam->key)->toBe('provider.operation_start_gate')
        ->and($seam->owner->value)->toBeIn(ProviderBoundaryOwner::values())
        ->and($seam->description)->not->toBeEmpty()
        ->and($seam->implementationPaths)->not->toBeEmpty()
        ->and($seam->neutralTerms)->not->toBeEmpty()
        ->and($seam->retainedProviderSemantics)->toContain('provider_context.microsoft_tenant_id')
        ->and($seam->followUpAction)->toBeIn([
            ProviderBoundarySeam::FOLLOW_UP_NONE,
            ProviderBoundarySeam::FOLLOW_UP_DOCUMENT_IN_FEATURE,
            ProviderBoundarySeam::FOLLOW_UP_SPEC,
        ]);
});
