<?php

use App\Jobs\BulkPolicySyncJob;
use App\Models\AuditLog;
use App\Models\BulkOperationRun;
use App\Models\Policy;
use App\Models\Tenant;
use App\Models\User;
use App\Services\BulkOperationService;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('bulk sync updates selected policies from graph', function () {
    $tenant = Tenant::factory()->create();
    $tenant->makeCurrent();
    $user = User::factory()->create();

    $policies = Policy::factory()
        ->count(3)
        ->create([
            'tenant_id' => $tenant->id,
            'policy_type' => 'deviceConfiguration',
            'platform' => 'windows10AndLater',
            'last_synced_at' => null,
        ]);

    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, [
                'payload' => [
                    'id' => $policyId,
                    'displayName' => "Synced {$policyId}",
                    'platform' => $options['platform'] ?? null,
                    'example' => 'value',
                ],
            ]);
        }

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

    $service = app(BulkOperationService::class);
    $run = $service->createRun($tenant, $user, 'policy', 'sync', $policies->modelKeys(), 3);

    BulkPolicySyncJob::dispatchSync($run->id);

    $bulkRun = BulkOperationRun::query()->find($run->id);
    expect($bulkRun)->not->toBeNull();
    expect($bulkRun->status)->toBe('completed');
    expect($bulkRun->total_items)->toBe(3);
    expect($bulkRun->succeeded)->toBe(3);
    expect($bulkRun->failed)->toBe(0);

    $policies->each(function (Policy $policy) {
        $policy->refresh();

        expect($policy->last_synced_at)->not->toBeNull();
        expect($policy->display_name)->toBe("Synced {$policy->external_id}");
        expect($policy->metadata)->toMatchArray([
            'example' => 'value',
        ]);
    });

    expect(AuditLog::where('action', 'bulk.policy.sync.completed')->exists())->toBeTrue();
});
