<?php

declare(strict_types=1);

use App\Services\Auth\RoleCapabilityMap;
use App\Services\Intune\ManagedEnvironmentPermissionService;
use App\Support\Auth\Capabilities;
use App\Support\TenantRole;

it('has ENTRA_ROLES_VIEW and ENTRA_ROLES_MANAGE capability constants', function (): void {
    expect(Capabilities::ENTRA_ROLES_VIEW)->toBe('entra_roles.view')
        ->and(Capabilities::ENTRA_ROLES_MANAGE)->toBe('entra_roles.manage');
});

it('includes ENTRA_ROLES_VIEW in all() capability registry', function (): void {
    $all = Capabilities::all();

    expect($all)->toContain(Capabilities::ENTRA_ROLES_VIEW)
        ->and($all)->toContain(Capabilities::ENTRA_ROLES_MANAGE);
});

it('maps ENTRA_ROLES_VIEW to Readonly and Operator roles', function (): void {
    expect(RoleCapabilityMap::hasCapability(TenantRole::Readonly, Capabilities::ENTRA_ROLES_VIEW))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Operator, Capabilities::ENTRA_ROLES_VIEW))->toBeTrue();
});

it('maps ENTRA_ROLES_MANAGE to Manager and Owner roles only', function (): void {
    expect(RoleCapabilityMap::hasCapability(TenantRole::Owner, Capabilities::ENTRA_ROLES_MANAGE))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Manager, Capabilities::ENTRA_ROLES_MANAGE))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Operator, Capabilities::ENTRA_ROLES_MANAGE))->toBeFalse()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Readonly, Capabilities::ENTRA_ROLES_MANAGE))->toBeFalse();
});

it('maps ENTRA_ROLES_VIEW to Manager and Owner roles', function (): void {
    expect(RoleCapabilityMap::hasCapability(TenantRole::Owner, Capabilities::ENTRA_ROLES_VIEW))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Manager, Capabilities::ENTRA_ROLES_VIEW))->toBeTrue();
});

// ---------------------------------------------------------------------------
// T028 — ManagedEnvironmentPermissionService merge tests
// ---------------------------------------------------------------------------

it('merged required permissions include both Intune and Entra entries', function (): void {
    $service = app(ManagedEnvironmentPermissionService::class);
    $permissions = $service->getRequiredPermissions();

    $keys = array_column($permissions, 'key');

    // At least one Intune permission
    expect($keys)->toContain('DeviceManagementConfiguration.ReadWrite.All')
        // And the Entra permission
        ->and($keys)->toContain('RoleManagement.Read.Directory');
});

it('RoleManagement.Read.Directory has correct type and features in merged list', function (): void {
    $service = app(ManagedEnvironmentPermissionService::class);
    $permissions = $service->getRequiredPermissions();

    $entraPermission = collect($permissions)->firstWhere('key', 'RoleManagement.Read.Directory');

    expect($entraPermission)->not->toBeNull()
        ->and($entraPermission['type'])->toBe('application')
        ->and($entraPermission['features'])->toContain('entra-admin-roles');
});

it('existing Intune permissions unchanged after Entra merge', function (): void {
    $service = app(ManagedEnvironmentPermissionService::class);
    $merged = $service->getRequiredPermissions();

    $intuneOnly = config('intune_permissions.permissions', []);
    $intuneKeys = array_column($intuneOnly, 'key');

    foreach ($intuneKeys as $key) {
        $original = collect($intuneOnly)->firstWhere('key', $key);
        $inMerged = collect($merged)->firstWhere('key', $key);

        expect($inMerged)->not->toBeNull()
            ->and($inMerged['key'])->toBe($original['key'])
            ->and($inMerged['type'])->toBe($original['type']);
    }
});

it('empty entra_permissions config returns only Intune entries', function (): void {
    config()->set('entra_permissions.permissions', []);

    $service = app(ManagedEnvironmentPermissionService::class);
    $permissions = $service->getRequiredPermissions();

    $intuneOnly = config('intune_permissions.permissions', []);

    expect($permissions)->toHaveCount(count($intuneOnly));

    $keys = array_column($permissions, 'key');
    expect($keys)->not->toContain('RoleManagement.Read.Directory');
});
