<?php

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

uses(RefreshDatabase::class);

test('restore preview lists actions per backup item', function () {
    app()->bind(GraphClientInterface::class, fn () => 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' => []]);
        }

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

    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-1',
        'name' => 'ManagedEnvironment One',
        'metadata' => [],
    ]);
    ensureDefaultProviderConnection($tenant, 'microsoft');

    $policy = Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'policy-1',
        'policy_type' => 'deviceConfiguration',
        'display_name' => 'Policy A',
        'platform' => 'windows',
    ]);

    $backupSet = BackupSet::create([
        'managed_environment_id' => $tenant->id,
        'name' => 'Backup',
        'status' => 'completed',
        'item_count' => 1,
    ]);

    BackupItem::create([
        'managed_environment_id' => $tenant->id,
        'backup_set_id' => $backupSet->id,
        'policy_id' => $policy->id,
        'policy_identifier' => $policy->external_id,
        'policy_type' => $policy->policy_type,
        'platform' => $policy->platform,
        'payload' => ['foo' => 'bar'],
    ]);

    BackupItem::create([
        'managed_environment_id' => $tenant->id,
        'backup_set_id' => $backupSet->id,
        'policy_id' => null,
        'policy_identifier' => 'filter-1',
        'policy_type' => 'assignmentFilter',
        'platform' => 'all',
        'payload' => [
            'id' => 'filter-1',
            'displayName' => 'Filter One',
        ],
        'metadata' => [
            'displayName' => 'Filter One',
        ],
    ]);

    $service = app(RestoreService::class);
    $preview = $service->preview($tenant, $backupSet);

    expect($preview)->toHaveCount(2);

    $foundation = collect($preview)->first(fn (array $item) => isset($item['decision']));
    expect($foundation['decision'])->toBe('created');

    $policyPreview = collect($preview)->first(fn (array $item) => isset($item['action']));
    expect($policyPreview['action'])->toBe('update');
});

test('restore preview shows enabled restore mode for windows driver update profiles', function () {
    app()->bind(GraphClientInterface::class, fn () => 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' => []]);
        }

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

    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-driver-preview',
        'name' => 'ManagedEnvironment Preview',
        'metadata' => [],
    ]);
    ensureDefaultProviderConnection($tenant, 'microsoft');

    $backupSet = BackupSet::create([
        'managed_environment_id' => $tenant->id,
        'name' => 'Backup',
        'status' => 'completed',
        'item_count' => 1,
    ]);

    $backupItem = BackupItem::create([
        'managed_environment_id' => $tenant->id,
        'backup_set_id' => $backupSet->id,
        'policy_id' => null,
        'policy_identifier' => 'wdp-1',
        'policy_type' => 'windowsDriverUpdateProfile',
        'platform' => 'windows',
        'payload' => [
            '@odata.type' => '#microsoft.graph.windowsDriverUpdateProfile',
            'displayName' => 'Driver Updates A',
        ],
    ]);

    $service = app(RestoreService::class);
    $preview = $service->preview($tenant, $backupSet, [$backupItem->id]);

    expect($preview)->toHaveCount(1);

    $policyPreview = $preview[0] ?? [];
    expect($policyPreview['policy_type'] ?? null)->toBe('windowsDriverUpdateProfile');
    expect($policyPreview['action'] ?? null)->toBe('create');
    expect($policyPreview['restore_mode'] ?? null)->toBe('enabled');
});

test('restore preview warns about missing compliance notification templates', function () {
    app()->bind(GraphClientInterface::class, fn () => 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' => []]);
        }

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

    $tenant = ManagedEnvironment::create([
        'managed_environment_id' => 'tenant-2',
        'name' => 'ManagedEnvironment Two',
        'metadata' => [],
    ]);
    ensureDefaultProviderConnection($tenant, 'microsoft');

    $policy = Policy::create([
        'managed_environment_id' => $tenant->id,
        'external_id' => 'policy-2',
        'policy_type' => 'deviceCompliancePolicy',
        'display_name' => 'Compliance Policy',
        'platform' => 'windows',
    ]);

    $backupSet = BackupSet::create([
        'managed_environment_id' => $tenant->id,
        'name' => 'Backup',
        'status' => 'completed',
        'item_count' => 1,
    ]);

    BackupItem::create([
        'managed_environment_id' => $tenant->id,
        'backup_set_id' => $backupSet->id,
        'policy_id' => $policy->id,
        'policy_identifier' => $policy->external_id,
        'policy_type' => $policy->policy_type,
        'platform' => $policy->platform,
        'payload' => [
            'scheduledActionsForRule' => [
                [
                    'ruleName' => 'Password',
                    'scheduledActionConfigurations' => [
                        [
                            'actionType' => 'notification',
                            'notificationTemplateId' => 'template-1',
                        ],
                    ],
                ],
            ],
        ],
    ]);

    $service = app(RestoreService::class);
    $preview = $service->preview($tenant, $backupSet);

    $policyPreview = collect($preview)->first(fn (array $item) => ($item['policy_type'] ?? null) === 'deviceCompliancePolicy');

    expect($policyPreview['compliance_action_warning'] ?? null)->not->toBeNull();
    expect(($policyPreview['compliance_action_summary']['missing'] ?? 0))->toBe(1);
    expect($policyPreview['compliance_action_missing_templates'] ?? [])->toContain('template-1');
});
