<?php

namespace Tests\Unit\Identity;

use App\Domain\Identity\Enums\PermissionScope;
use App\Domain\Identity\Services\PermissionRegistry;
use App\Domain\Identity\Services\RoleRegistry;
use PHPUnit\Framework\TestCase;

class PermissionScopeTest extends TestCase
{
    public function test_scopes_are_ordered_from_narrow_to_wide(): void
    {
        $this->assertTrue(PermissionScope::Global->isAtLeast(PermissionScope::Own));
        $this->assertTrue(PermissionScope::Branch->isAtLeast(PermissionScope::Team));
        $this->assertFalse(PermissionScope::Own->isAtLeast(PermissionScope::Branch));
        $this->assertTrue(PermissionScope::Team->isAtLeast(PermissionScope::Team));
    }

    public function test_widest_picks_the_largest_scope(): void
    {
        $this->assertSame(
            PermissionScope::Company,
            PermissionScope::widest(PermissionScope::Own, PermissionScope::Company, PermissionScope::Team)
        );
        $this->assertNull(PermissionScope::widest());
    }

    public function test_wildcards_expand_to_concrete_permissions(): void
    {
        $resolved = RoleRegistry::resolvePermissions(['document.*' => 'branch']);

        $this->assertArrayHasKey('document.verify', $resolved);
        $this->assertSame('branch', $resolved['document.verify']);
        $this->assertArrayNotHasKey('payment.create', $resolved);
    }

    public function test_a_wildcard_never_narrows_an_explicit_wider_grant(): void
    {
        $resolved = RoleRegistry::resolvePermissions([
            'document.download_sensitive' => 'company',
            'document.*' => 'own',
        ]);

        $this->assertSame('company', $resolved['document.download_sensitive']);
        $this->assertSame('own', $resolved['document.upload']);
    }

    public function test_super_admin_holds_every_permission_globally(): void
    {
        $resolved = RoleRegistry::resolvePermissions(RoleRegistry::roles()['super-admin']['permissions']);

        $this->assertCount(count(PermissionRegistry::names()), $resolved);
        $this->assertSame(['global'], array_values(array_unique($resolved)));
    }

    public function test_every_role_grant_references_a_registered_permission(): void
    {
        $known = PermissionRegistry::names();

        foreach (RoleRegistry::roles() as $name => $definition) {
            foreach (RoleRegistry::resolvePermissions($definition['permissions']) as $permission => $scope) {
                $this->assertContains($permission, $known, "Role [{$name}] grants unknown permission [{$permission}].");
                $this->assertNotNull(PermissionScope::tryFrom($scope));
            }
        }
    }
}
