<?php

use App\Services\Intune\IntuneRoleDefinitionNormalizer;

it('normalizes built-in intune role definitions into readable permission blocks', function (): void {
    $normalizer = app(IntuneRoleDefinitionNormalizer::class);

    $snapshot = [
        '@odata.type' => '#microsoft.graph.deviceAndAppManagementRoleDefinition',
        'displayName' => 'Policy and Profile Manager',
        'description' => 'Built-in RBAC role',
        'isBuiltIn' => true,
        'rolePermissions' => [
            [
                'resourceActions' => [
                    [
                        'allowedResourceActions' => [
                            'Microsoft.Intune/deviceConfigurations/read',
                            'Microsoft.Intune/deviceConfigurations/create',
                        ],
                        'notAllowedResourceActions' => [
                            'Microsoft.Intune/deviceConfigurations/delete',
                        ],
                    ],
                ],
            ],
        ],
        'roleScopeTagIds' => ['scope-1', '0'],
    ];

    $result = $normalizer->normalize($snapshot, 'intuneRoleDefinition', 'all');

    $summary = collect($result['settings'])->firstWhere('title', 'Role definition');
    $permissionBlock = collect($result['settings'])->firstWhere('title', 'Permission block 1');
    $summaryEntries = collect($summary['entries'] ?? [])->keyBy('key');
    $permissionEntries = collect($permissionBlock['entries'] ?? [])->keyBy('key');

    expect($result['status'])->toBe('ok');
    expect($summaryEntries['Role source']['value'] ?? null)->toBe('Built-in');
    expect($summaryEntries['Permission blocks']['value'] ?? null)->toBe(1);
    expect($summaryEntries['Scope tag IDs']['value'] ?? null)->toBe(['scope-1', '0']);
    expect($permissionEntries['Allowed actions']['value'] ?? null)->toBe([
        'Microsoft.Intune/deviceConfigurations/create',
        'Microsoft.Intune/deviceConfigurations/read',
    ]);
    expect($permissionEntries['Denied actions']['value'] ?? null)->toBe([
        'Microsoft.Intune/deviceConfigurations/delete',
    ]);
});

it('flattens custom intune role definitions deterministically regardless of permission block order', function (): void {
    $normalizer = app(IntuneRoleDefinitionNormalizer::class);

    $firstSnapshot = [
        'displayName' => 'Custom RBAC Role',
        'isBuiltIn' => false,
        'rolePermissions' => [
            [
                'resourceActions' => [
                    [
                        'allowedResourceActions' => [
                            'Microsoft.Intune/deviceCompliancePolicies/read',
                        ],
                    ],
                ],
            ],
            [
                'resourceActions' => [
                    [
                        'allowedResourceActions' => [
                            'Microsoft.Intune/deviceConfigurations/read',
                        ],
                        'condition' => '@Resource[Microsoft.Intune/deviceConfigurations] Exists',
                    ],
                ],
            ],
        ],
    ];

    $secondSnapshot = [
        'displayName' => 'Custom RBAC Role',
        'isBuiltIn' => false,
        'rolePermissions' => [
            $firstSnapshot['rolePermissions'][1],
            $firstSnapshot['rolePermissions'][0],
        ],
    ];

    expect($normalizer->flattenForDiff($firstSnapshot, 'intuneRoleDefinition', 'all'))
        ->toBe($normalizer->flattenForDiff($secondSnapshot, 'intuneRoleDefinition', 'all'));
});

it('classifies metadata-only role definition changes separately from permission changes', function (): void {
    $normalizer = app(IntuneRoleDefinitionNormalizer::class);

    $baselineSnapshot = [
        'displayName' => 'Custom RBAC Role',
        'description' => 'Baseline description',
        'isBuiltIn' => false,
        'rolePermissions' => [
            [
                'resourceActions' => [
                    [
                        'allowedResourceActions' => [
                            'Microsoft.Intune/deviceConfigurations/read',
                        ],
                    ],
                ],
            ],
        ],
        'roleScopeTagIds' => ['0'],
    ];

    $metadataOnlySnapshot = $baselineSnapshot;
    $metadataOnlySnapshot['description'] = 'Updated description';

    $permissionChangedSnapshot = $baselineSnapshot;
    $permissionChangedSnapshot['rolePermissions'][0]['resourceActions'][0]['allowedResourceActions'][] = 'Microsoft.Intune/deviceConfigurations/delete';

    $metadataDiff = $normalizer->classifyDiff($baselineSnapshot, $metadataOnlySnapshot, 'all');
    $permissionDiff = $normalizer->classifyDiff($baselineSnapshot, $permissionChangedSnapshot, 'all');

    expect($metadataDiff['diff_kind'])->toBe('metadata_only');
    expect($metadataDiff['changed_keys'])->toBe([
        'Role definition > Description',
    ]);
    expect($metadataDiff['metadata_keys'])->toBe([
        'Role definition > Description',
    ]);
    expect($metadataDiff['permission_keys'])->toBe([]);
    expect($metadataDiff['diff_fingerprint'])->not->toBe($permissionDiff['diff_fingerprint']);

    expect($permissionDiff['diff_kind'])->toBe('permission_change');
    expect($permissionDiff['changed_keys'])->toContain('Permission block 1 > Allowed actions');
    expect($permissionDiff['permission_keys'])->toContain('Permission block 1 > Allowed actions');
});
