<?php

declare(strict_types=1);

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

use App\Module\Core\Domain\Entity\Permission;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;

/**
 * @internal
 */
final class PermissionTest extends TestCase
{
    public function testConstructorInitialState(): void
    {
        $permission = new Permission('core.users.view', 'Voir les utilisateurs', 'core');

        self::assertNull($permission->getId());
        self::assertSame('core.users.view', $permission->getCode());
        self::assertSame('Voir les utilisateurs', $permission->getLabel());
        self::assertSame('core', $permission->getModule());
        self::assertFalse($permission->isOrphan());
    }

    public function testMarkOrphanSetsFlag(): void
    {
        $permission = new Permission('core.users.view', 'Voir les utilisateurs', 'core');

        $permission->markOrphan();

        self::assertTrue($permission->isOrphan());
    }

    public function testReviveResetsOrphanAndUpdatesMetadata(): void
    {
        $permission = new Permission('core.users.view', 'Old label', 'core');
        $permission->markOrphan();

        $permission->revive('New label', 'commercial');

        self::assertFalse($permission->isOrphan());
        self::assertSame('New label', $permission->getLabel());
        self::assertSame('commercial', $permission->getModule());
    }

    public function testUpdateMetadataDoesNotTouchOrphan(): void
    {
        $permission = new Permission('core.users.view', 'Old', 'core');
        $permission->markOrphan();

        $permission->updateMetadata('Lbl', 'core');

        self::assertTrue($permission->isOrphan());
        self::assertSame('Lbl', $permission->getLabel());
    }

    public function testConstructorRejectsEmptyCode(): void
    {
        $this->expectException(InvalidArgumentException::class);

        new Permission('', 'Libelle', 'core');
    }

    public function testConstructorRejectsCodeWithoutDot(): void
    {
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('invalid_format');

        new Permission('invalid_format', 'Libelle', 'core');
    }

    public function testConstructorRejectsEmptyLabel(): void
    {
        $this->expectException(InvalidArgumentException::class);

        new Permission('core.users.view', '', 'core');
    }

    public function testConstructorRejectsEmptyModule(): void
    {
        $this->expectException(InvalidArgumentException::class);

        new Permission('core.users.view', 'Libelle', '');
    }
}
