<?php

use App\Jobs\ProviderComplianceSnapshotJob;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use App\Services\OperationRunService;

it('writes compliance summary_counts and marks the run succeeded', function (): void {
    app()->instance(GraphClientInterface::class, new class implements GraphClientInterface
    {
        public function listPolicies(string $policyType, array $options = []): GraphResponse
        {
            return new GraphResponse(true);
        }

        public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
        {
            return new GraphResponse(true);
        }

        public function getOrganization(array $options = []): GraphResponse
        {
            return new GraphResponse(true, data: ['displayName' => 'Contoso']);
        }

        public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
        {
            return new GraphResponse(true);
        }

        public function getServicePrincipalPermissions(array $options = []): GraphResponse
        {
            return new GraphResponse(true);
        }

        public function request(string $method, string $path, array $options = []): GraphResponse
        {
            return new GraphResponse(true, data: [
                'value' => [
                    ['id' => '1', 'complianceState' => 'compliant'],
                    ['id' => '2', 'complianceState' => 'noncompliant'],
                    ['id' => '3', 'complianceState' => null],
                ],
            ]);
        }
    });

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

    $connection = ProviderConnection::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => fake()->uuid(),
    ]);

    ProviderCredential::factory()->create([
        'provider_connection_id' => $connection->getKey(),
        'payload' => [
            'client_id' => 'client-id',
            'client_secret' => 'client-secret',
        ],
    ]);

    $run = OperationRun::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'user_id' => $user->getKey(),
        'initiator_name' => $user->name,
        'type' => 'compliance.snapshot',
        'status' => 'running',
        'outcome' => 'pending',
        'context' => [
            'provider' => 'microsoft',
            'module' => 'compliance',
            'provider_connection_id' => (int) $connection->getKey(),
            'target_scope' => [
                'entra_tenant_id' => $connection->entra_tenant_id,
            ],
        ],
    ]);

    $job = new ProviderComplianceSnapshotJob(
        tenantId: (int) $tenant->getKey(),
        userId: (int) $user->getKey(),
        providerConnectionId: (int) $connection->getKey(),
        operationRun: $run,
    );

    $job->handle(
        app(\App\Services\Providers\MicrosoftComplianceSnapshotService::class),
        app(\App\Services\Providers\ProviderGateway::class),
        app(OperationRunService::class),
    );

    $run->refresh();

    expect($run->status)->toBe('completed');
    expect($run->outcome)->toBe('succeeded');
    expect($run->summary_counts)->toMatchArray([
        'total' => 3,
        'compliant' => 1,
        'noncompliant' => 1,
        'unknown' => 1,
    ]);

    expect($run->context)->toMatchArray([
        'provider' => 'microsoft',
        'module' => 'compliance',
        'provider_connection_id' => (int) $connection->getKey(),
        'connection_type' => 'platform',
    ]);
    expect($run->context['provider_context'] ?? [])->toMatchArray([
        'provider' => 'microsoft',
    ]);
    expect($run->context['target_scope'] ?? [])->toMatchArray([
        'provider' => 'microsoft',
        'scope_kind' => 'tenant',
        'scope_identifier' => $connection->entra_tenant_id,
        'scope_display_name' => 'Contoso',
    ])->not->toHaveKey('entra_tenant_id');
});
