<?php

declare(strict_types=1);

use App\Jobs\CaptureBaselineSnapshotJob;
use App\Jobs\CompareBaselineToTenantJob;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment;
use App\Services\Baselines\BaselineCaptureService;
use App\Services\Baselines\BaselineCompareService;
use App\Support\Baselines\BaselineCaptureMode;
use App\Support\Baselines\BaselineReasonCodes;
use App\Support\Baselines\BaselineSupportCapabilityGuard;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;

uses(RefreshDatabase::class);

function appendBrokenFoundationSupportConfig(): void
{
    $foundationTypes = is_array(config('tenantpilot.foundation_types')) ? config('tenantpilot.foundation_types') : [];
    $foundationTypes[] = [
        'type' => 'brokenFoundation',
        'label' => 'Broken Foundation',
        'baseline_compare' => [
            'supported' => true,
            'identity_strategy' => 'external_id',
            'resolution' => [
                'subject_class' => 'foundation_backed',
                'resolution_path' => 'foundation_policy',
                'compare_capability' => 'supported',
                'capture_capability' => 'supported',
                'source_model_expected' => 'inventory',
            ],
        ],
    ];

    config()->set('tenantpilot.foundation_types', $foundationTypes);
}

it('persists truthful compare scope capability decisions before dispatching compare work', function (): void {
    Bus::fake();
    appendBrokenFoundationSupportConfig();

    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $profile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'capture_mode' => BaselineCaptureMode::Opportunistic->value,
        'scope_jsonb' => [
            'policy_types' => ['deviceConfiguration'],
            'foundation_types' => ['roleScopeTag', 'brokenFoundation', 'unknownFoundation'],
        ],
    ]);

    $snapshot = BaselineSnapshot::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'baseline_profile_id' => (int) $profile->getKey(),
    ]);

    $profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]);

    BaselineTenantAssignment::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'baseline_profile_id' => (int) $profile->getKey(),
    ]);

    $result = app(BaselineCompareService::class)->startCompare($tenant, $user);

    expect($result['ok'])->toBeTrue();

    $run = $result['run'];
    $scope = data_get($run->context, 'effective_scope');

    expect(data_get($scope, 'truthful_types'))->toBe(['deviceConfiguration', 'roleScopeTag'])
        ->and(data_get($scope, 'limited_types'))->toBe(['roleScopeTag'])
        ->and(data_get($scope, 'all_types'))->toBe(['brokenFoundation', 'deviceConfiguration', 'roleScopeTag'])
        ->and(data_get($scope, 'unsupported_types'))->toBe(['brokenFoundation'])
        ->and(data_get($scope, 'invalid_support_types'))->toBe(['brokenFoundation'])
        ->and(data_get($scope, 'capabilities.deviceConfiguration.support_mode'))->toBe('supported')
        ->and(data_get($scope, 'capabilities.roleScopeTag.support_mode'))->toBe('limited')
        ->and(data_get($scope, 'capabilities.brokenFoundation.support_mode'))->toBe('invalid_support_config')
        ->and(data_get($scope, 'capabilities.unknownFoundation.support_mode'))->toBeNull();

    Bus::assertDispatched(CompareBaselineToTenantJob::class);
});

it('blocks capture work when the scope still contains unsupported types, while preserving truthful capability context', function (): void {
    Bus::fake();
    appendBrokenFoundationSupportConfig();

    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $profile = BaselineProfile::factory()->active()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'capture_mode' => BaselineCaptureMode::Opportunistic->value,
        'scope_jsonb' => [
            'policy_types' => ['deviceConfiguration'],
            'foundation_types' => ['roleScopeTag', 'brokenFoundation', 'unknownFoundation'],
        ],
    ]);

    $result = app(BaselineCaptureService::class)->startCapture($profile, $tenant, $user);

    $scope = $profile->normalizedScope()->toEffectiveScopeContext(
        app(BaselineSupportCapabilityGuard::class),
        'capture',
    );

    expect($result['ok'])->toBeFalse()
        ->and($result['reason_code'] ?? null)->toBe(BaselineReasonCodes::CAPTURE_UNSUPPORTED_SCOPE);

    expect(data_get($scope, 'truthful_types'))->toBe(['deviceConfiguration', 'roleScopeTag'])
        ->and(data_get($scope, 'limited_types'))->toBe(['roleScopeTag'])
        ->and(data_get($scope, 'all_types'))->toBe(['brokenFoundation', 'deviceConfiguration', 'roleScopeTag'])
        ->and(data_get($scope, 'unsupported_types'))->toBe(['brokenFoundation'])
        ->and(data_get($scope, 'invalid_support_types'))->toBe(['brokenFoundation'])
        ->and(data_get($scope, 'capabilities.deviceConfiguration.support_mode'))->toBe('supported')
        ->and(data_get($scope, 'capabilities.roleScopeTag.support_mode'))->toBe('limited')
        ->and(data_get($scope, 'capabilities.brokenFoundation.support_mode'))->toBe('invalid_support_config')
        ->and(data_get($scope, 'capabilities.unknownFoundation.support_mode'))->toBeNull();

    Bus::assertNotDispatched(CaptureBaselineSnapshotJob::class);
});
