<?php

use App\Models\Policy;
use App\Models\ManagedEnvironment;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use App\Services\Intune\PolicySyncService;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

class FakeGraphClientForAppProtectionSync implements GraphClientInterface
{
    /**
     * @param  array<string, GraphResponse>  $responses
     */
    public function __construct(private array $responses = []) {}

    public function listPolicies(string $policyType, array $options = []): GraphResponse
    {
        return $this->responses[$policyType] ?? 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, []);
    }

    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, []);
    }
}

test('sync skips managed app configurations from app protection inventory', function () {
    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'test-tenant',
        'name' => 'Test ManagedEnvironment',
        'metadata' => [],
        'is_current' => true,
    ]);

    ensureDefaultProviderConnection($tenant);

    Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'config-1',
        'policy_type' => 'appProtectionPolicy',
        'display_name' => 'Config 1 (legacy)',
        'platform' => 'mobile',
        'ignored_at' => null,
    ]);

    $responses = [
        'appProtectionPolicy' => new GraphResponse(true, [
            [
                'id' => 'config-1',
                'displayName' => 'Config 1',
                '@odata.type' => '#microsoft.graph.targetedManagedAppConfiguration',
            ],
            [
                'id' => 'config-skip',
                'displayName' => 'Config skip',
                '@odata.type' => '#microsoft.graph.targetedManagedAppConfiguration',
            ],
            [
                'id' => 'policy-2',
                'displayName' => 'MAM Policy',
                '@odata.type' => '#microsoft.graph.iosManagedAppProtection',
            ],
        ]),
    ];

    app()->instance(GraphClientInterface::class, new FakeGraphClientForAppProtectionSync($responses));

    app(PolicySyncService::class)->syncPolicies($tenant);

    $existingConfig = Policy::query()
        ->where('managed_environment_id', $tenant->id)
        ->where('policy_type', 'appProtectionPolicy')
        ->where('external_id', 'config-1')
        ->firstOrFail();

    expect($existingConfig->ignored_at)->toBeNull();
    expect($existingConfig->missing_from_provider_at)->not->toBeNull();
    expect(Policy::where('managed_environment_id', $tenant->id)->where('external_id', 'config-skip')->exists())->toBeFalse();
    expect(Policy::where('managed_environment_id', $tenant->id)->where('external_id', 'policy-2')->whereNull('ignored_at')->whereNull('missing_from_provider_at')->exists())->toBeTrue();
});
