<?php

declare(strict_types=1);

use App\Support\Baselines\BaselineSupportCapabilityGuard;
use App\Support\Baselines\OperatorActionCategory;
use App\Support\Baselines\ResolutionOutcome;
use App\Support\Baselines\ResolutionPath;
use App\Support\Baselines\SubjectClass;
use App\Support\Baselines\SubjectResolver;

it('derives truthful runtime capability and descriptors for supported policy and foundation types', function (): void {
    $resolver = app(SubjectResolver::class);

    $policyDescriptor = $resolver->describeForCompare('deviceConfiguration', 'policy-1', 'deviceconfiguration|policy-1');
    $foundationDescriptor = $resolver->describeForCapture('roleScopeTag', 'scope-tag-1', 'rolescopetag|baseline');
    $rbacDescriptor = $resolver->describeForCompare('intuneRoleDefinition', 'role-def-1', 'rbac-role');

    expect($policyDescriptor->subjectClass)->toBe(SubjectClass::PolicyBacked)
        ->and($policyDescriptor->resolutionPath)->toBe(ResolutionPath::Policy)
        ->and($policyDescriptor->supportMode)->toBe('supported')
        ->and($policyDescriptor->sourceModelExpected)->toBe('policy');

    expect($foundationDescriptor->subjectClass)->toBe(SubjectClass::FoundationBacked)
        ->and($foundationDescriptor->resolutionPath)->toBe(ResolutionPath::FoundationInventory)
        ->and($foundationDescriptor->supportMode)->toBe('limited')
        ->and($foundationDescriptor->sourceModelExpected)->toBe('inventory');

    expect($rbacDescriptor->subjectClass)->toBe(SubjectClass::FoundationBacked)
        ->and($rbacDescriptor->resolutionPath)->toBe(ResolutionPath::FoundationPolicy)
        ->and($rbacDescriptor->supportMode)->toBe('supported')
        ->and($rbacDescriptor->sourceModelExpected)->toBe('policy');
});

it('maps structural and operational outcomes without flattening them into policy_not_found', function (): void {
    $resolver = app(SubjectResolver::class);

    $foundationDescriptor = $resolver->describeForCapture('notificationMessageTemplate', 'template-1', 'template-subject');
    $policyDescriptor = $resolver->describeForCompare('deviceConfiguration', 'policy-1', 'policy-subject');

    $structuralOutcome = $resolver->structuralInventoryOnly($foundationDescriptor);
    $missingPolicyOutcome = $resolver->missingExpectedRecord($policyDescriptor);
    $throttledOutcome = $resolver->throttled($policyDescriptor);

    expect($structuralOutcome->resolutionOutcome)->toBe(ResolutionOutcome::FoundationInventoryOnly)
        ->and($structuralOutcome->reasonCode)->toBe('foundation_not_policy_backed')
        ->and($structuralOutcome->operatorActionCategory)->toBe(OperatorActionCategory::ProductFollowUp)
        ->and($structuralOutcome->structural)->toBeTrue();

    expect($missingPolicyOutcome->resolutionOutcome)->toBe(ResolutionOutcome::PolicyRecordMissing)
        ->and($missingPolicyOutcome->reasonCode)->toBe('policy_record_missing')
        ->and($missingPolicyOutcome->operatorActionCategory)->toBe(OperatorActionCategory::RunPolicySyncOrBackup)
        ->and($missingPolicyOutcome->structural)->toBeFalse();

    expect($throttledOutcome->resolutionOutcome)->toBe(ResolutionOutcome::Throttled)
        ->and($throttledOutcome->retryable)->toBeTrue()
        ->and($throttledOutcome->operatorActionCategory)->toBe(OperatorActionCategory::Retry);
});

it('guards unsupported or invalid support declarations before runtime work starts', function (): void {
    $guard = app(BaselineSupportCapabilityGuard::class);

    config()->set('tenantpilot.foundation_types', [
        [
            'type' => 'intuneRoleAssignment',
            'label' => 'Intune RBAC Role Assignment',
            'baseline_compare' => [
                'supported' => false,
                'identity_strategy' => 'external_id',
            ],
        ],
        [
            'type' => 'brokenFoundation',
            'label' => 'Broken Foundation',
            'baseline_compare' => [
                'supported' => true,
                'resolution' => [
                    'subject_class' => SubjectClass::FoundationBacked->value,
                    'resolution_path' => 'broken',
                    'compare_capability' => 'supported',
                    'capture_capability' => 'supported',
                    'source_model_expected' => 'inventory',
                ],
            ],
        ],
    ]);

    $result = $guard->guardTypes(['intuneRoleAssignment', 'brokenFoundation'], 'compare');

    expect($result['allowed_types'])->toBe([])
        ->and($result['unsupported_types'])->toBe(['brokenFoundation', 'intuneRoleAssignment'])
        ->and($result['invalid_support_types'])->toBe(['brokenFoundation'])
        ->and(data_get($result, 'capabilities.brokenFoundation.support_mode'))->toBe('invalid_support_config')
        ->and(data_get($result, 'capabilities.intuneRoleAssignment.support_mode'))->toBe('excluded');
});
