<?php

declare(strict_types=1);

namespace App\Tests\Module\Core\Domain\Entity;

use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Entity\Role;
use App\Module\Core\Domain\Exception\SystemRoleDeletionException;
use PHPUnit\Framework\TestCase;

/**
 * @internal
 */
final class RoleTest extends TestCase
{
    public function testConstructorInitialState(): void
    {
        $role = new Role('custom', 'Custom');

        self::assertNull($role->getId());
        self::assertSame('custom', $role->getCode());
        self::assertSame('Custom', $role->getLabel());
        self::assertNull($role->getDescription());
        self::assertFalse($role->isSystem());
        self::assertTrue($role->getPermissions()->isEmpty());
    }

    public function testAddPermissionAddsOnce(): void
    {
        $role       = new Role('custom', 'Custom');
        $permission = new Permission('core.users.view', 'Voir', 'core');

        $role->addPermission($permission);
        $role->addPermission($permission);

        self::assertSame(1, $role->getPermissions()->count());
    }

    public function testAddPermissionAddsMultipleDistinct(): void
    {
        $role           = new Role('custom', 'Custom');
        $permissionView = new Permission('core.users.view', 'Voir', 'core');
        $permissionEdit = new Permission('core.users.edit', 'Editer', 'core');

        $role->addPermission($permissionView);
        $role->addPermission($permissionEdit);

        self::assertSame(2, $role->getPermissions()->count());
    }

    public function testRemovePermissionRemovesWhenPresent(): void
    {
        $role       = new Role('custom', 'Custom');
        $permission = new Permission('core.users.view', 'Voir', 'core');

        $role->addPermission($permission);
        $role->removePermission($permission);

        self::assertSame(0, $role->getPermissions()->count());
    }

    public function testRemovePermissionIsNoOpWhenAbsent(): void
    {
        $role       = new Role('custom', 'Custom');
        $permission = new Permission('core.users.view', 'Voir', 'core');

        $role->removePermission($permission);

        self::assertSame(0, $role->getPermissions()->count());
    }

    public function testEnsureDeletableAllowsNonSystemRole(): void
    {
        $role = new Role('custom', 'Custom', false);

        $role->ensureDeletable();

        $this->expectNotToPerformAssertions();
    }

    public function testEnsureDeletableThrowsForSystemRole(): void
    {
        $role = new Role('admin', 'Admin', true);

        $this->expectException(SystemRoleDeletionException::class);
        $this->expectExceptionMessage('admin');

        $role->ensureDeletable();
    }
}
