<?php

declare(strict_types=1);

use App\Models\Policy;
use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Models\ManagedEnvironment;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphLogger;
use App\Services\Graph\GraphResponse;
use App\Services\Intune\PolicySyncService;

use function Pest\Laravel\mock;

function tenantWithDefaultMicrosoftConnectionForPolicySyncReport(array $attributes = []): ManagedEnvironment
{
    $tenant = ManagedEnvironment::factory()->create($attributes + [
        'status' => 'active',
        'app_client_id' => null,
        'app_client_secret' => null,
    ]);

    $connection = ProviderConnection::factory()->consentGranted()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'provider' => 'microsoft',
        'is_default' => true,
        'consent_status' => 'granted',
        'entra_tenant_id' => (string) ($tenant->managed_environment_id ?: 'tenant-'.$tenant->getKey()),
    ]);

    ProviderCredential::factory()->create([
        'provider_connection_id' => (int) $connection->getKey(),
        'type' => 'client_secret',
        'payload' => [
            'client_id' => 'provider-client-'.$tenant->getKey(),
            'client_secret' => 'provider-secret-'.$tenant->getKey(),
        ],
    ]);

    return $tenant;
}

it('returns a report with failures when policy list calls fail', function () {
    $tenant = tenantWithDefaultMicrosoftConnectionForPolicySyncReport();

    $logger = mock(GraphLogger::class);
    $logger->shouldReceive('logRequest')->zeroOrMoreTimes()->andReturnNull();
    $logger->shouldReceive('logResponse')->zeroOrMoreTimes()->andReturnNull();

    mock(GraphClientInterface::class)
        ->shouldReceive('listPolicies')
        ->andReturnUsing(function (string $policyType) {
            return match ($policyType) {
                'endpointSecurityPolicy' => new GraphResponse(
                    success: false,
                    data: [],
                    status: 403,
                    errors: [['message' => 'Forbidden']],
                    meta: ['path' => '/deviceManagement/configurationPolicies'],
                ),
                default => new GraphResponse(
                    success: true,
                    data: [
                        ['id' => 'scp-1', 'displayName' => 'Settings Catalog', 'technologies' => ['mdm']],
                    ],
                    status: 200,
                ),
            };
        });

    $service = app(PolicySyncService::class);

    $result = $service->syncPoliciesWithReport($tenant, [
        ['type' => 'endpointSecurityPolicy', 'platform' => 'windows'],
        ['type' => 'settingsCatalogPolicy', 'platform' => 'windows'],
    ]);

    expect($result)->toHaveKeys(['synced', 'failures']);
    expect($result['synced'])->toBeArray();
    expect($result['failures'])->toBeArray();

    expect(count($result['synced']))->toBe(1);
    expect(Policy::query()->where('managed_environment_id', $tenant->id)->count())->toBe(1);

    expect(count($result['failures']))->toBe(1);
    expect($result['failures'][0]['policy_type'])->toBe('endpointSecurityPolicy');
    expect($result['failures'][0]['status'])->toBe(403);
});
