<?php

use App\Services\Intune\IntuneRoleAssignmentNormalizer;

it('normalizes intune role assignments with readable role, member, and scope details', function (): void {
    $normalizer = app(IntuneRoleAssignmentNormalizer::class);

    $snapshot = [
        '@odata.type' => '#microsoft.graph.deviceAndAppManagementRoleAssignment',
        'displayName' => 'Helpdesk Assignment',
        'description' => 'Delegated access for helpdesk operators',
        'scopeType' => 'allDevicesAssignment',
        'members' => [
            ['displayName' => 'Helpdesk Group', 'id' => 'group-1'],
            'group-2',
        ],
        'scopeMembers' => [
            ['displayName' => 'Berlin Devices', 'id' => 'scope-group-1'],
        ],
        'resourceScopes' => [
            '/deviceManagement/managedDevices',
            '/',
        ],
        'roleDefinition' => [
            'id' => 'role-1',
            'displayName' => 'Policy and Profile Manager',
        ],
    ];

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

    $summary = collect($result['settings'])->firstWhere('title', 'Role assignment');
    $members = collect($result['settings'])->firstWhere('title', 'Members');
    $scopeMembers = collect($result['settings'])->firstWhere('title', 'Scope members');
    $resourceScopes = collect($result['settings'])->firstWhere('title', 'Resource scopes');
    $summaryEntries = collect($summary['entries'] ?? [])->keyBy('key');

    expect($result['status'])->toBe('ok');
    expect($summaryEntries['Role definition']['value'] ?? null)->toBe('Policy and Profile Manager (role-1)');
    expect($summaryEntries['Members count']['value'] ?? null)->toBe(2);
    expect($summaryEntries['Scope members count']['value'] ?? null)->toBe(1);
    expect($summaryEntries['Resource scopes count']['value'] ?? null)->toBe(2);
    expect($members['entries'][0]['value'] ?? null)->toBe([
        'Helpdesk Group (group-1)',
        'group-2',
    ]);
    expect($scopeMembers['entries'][0]['value'] ?? null)->toBe([
        'Berlin Devices (scope-group-1)',
    ]);
    expect($resourceScopes['entries'][0]['value'] ?? null)->toBe([
        '/',
        '/deviceManagement/managedDevices',
    ]);
});

it('uses identifier fallbacks and stable ordering when expanded role assignment data is incomplete', function (): void {
    $normalizer = app(IntuneRoleAssignmentNormalizer::class);

    $firstSnapshot = [
        'displayName' => 'Fallback Assignment',
        'members' => ['group-2', 'group-1'],
        'scopeMembers' => [
            ['id' => 'scope-2'],
            ['id' => 'scope-1'],
        ],
        'resourceScopes' => ['/b', '/a'],
        'roleDefinition' => [
            'id' => 'role-fallback',
        ],
    ];

    $secondSnapshot = [
        'displayName' => 'Fallback Assignment',
        'members' => ['group-1', 'group-2'],
        'scopeMembers' => [
            ['id' => 'scope-1'],
            ['id' => 'scope-2'],
        ],
        'resourceScopes' => ['/a', '/b'],
        'roleDefinition' => [
            'id' => 'role-fallback',
        ],
    ];

    $normalized = $normalizer->normalize($firstSnapshot, 'intuneRoleAssignment', 'all');
    $summary = collect($normalized['settings'])->firstWhere('title', 'Role assignment');
    $summaryEntries = collect($summary['entries'] ?? [])->keyBy('key');

    expect($normalized['status'])->toBe('warning');
    expect($normalized['warnings'])->toContain('Role definition display name unavailable; using identifier fallback.');
    expect($summaryEntries['Role definition']['value'] ?? null)->toBe('role-fallback');
    expect($normalizer->flattenForDiff($firstSnapshot, 'intuneRoleAssignment', 'all'))
        ->toBe($normalizer->flattenForDiff($secondSnapshot, 'intuneRoleAssignment', 'all'));
});
