<?php declare(strict_types=1);

namespace Apexl\Tests\User\FeatureTests;

use apexl\Io\modules\user\entities\roleEntity;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\enums\permissions\Common;
use apexl\Io\TestInfrastructure\FeatureTest;
use Apexl\Tests\User\Helpers\TestPermissionsEnum;
use PHPUnit\Framework\Attributes\Test;

final class PermissionsTest extends FeatureTest
{

    #[Test]
    public function managePermissionsDirectly(): void
    {
        $user = userEntity::factory()->create();
        $user->addPermission(TestPermissionsEnum::HAS_PERMISSION);

        $this->assertTrue($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
        $this->assertFalse($user->isAllowed(TestPermissionsEnum::DOES_NOT_HAVE_PERMISSION));

        $secondUser = userEntity::factory()->create();

        $this->assertFalse($secondUser->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
        $this->assertFalse($secondUser->isAllowed(TestPermissionsEnum::DOES_NOT_HAVE_PERMISSION));

        $user->removePermission(TestPermissionsEnum::HAS_PERMISSION);

        $this->assertFalse($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
    }

    #[Test]
    public function managePermissionsViaRole(): void
    {
        $user = userEntity::factory()->create();
        $role = roleEntity::factory()->create();

        $role->addPermission(TestPermissionsEnum::HAS_PERMISSION);
        $user->addRole($role);

        $this->assertTrue($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
        $this->assertFalse($user->isAllowed(TestPermissionsEnum::DOES_NOT_HAVE_PERMISSION));

        $secondUser = userEntity::factory()->create();

        $this->assertFalse($secondUser->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
        $this->assertFalse($secondUser->isAllowed(TestPermissionsEnum::DOES_NOT_HAVE_PERMISSION));

        $user->removeRole($role);

        $this->assertFalse($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));

        $role->removePermission(TestPermissionsEnum::HAS_PERMISSION);

        $user->addRole($role);
        $this->assertFalse($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
    }

    #[Test]
    public function common(): void
    {
        $user = userEntity::factory()->create();

        $this->assertTrue($user->isAllowed(Common::ALLOW_ALL));
        $this->assertFalse($user->isAllowed(Common::IS_LOGGED_IN));
        $this->assertFalse($user->isAllowed(Common::CAN_DO_NOTHING));
    }

    #[Test]
    public function bypass(): void
    {
        $user = userEntity::factory()->create();
        $role = roleEntity::factory()->create();
        $role->addPermission(Common::BYPASS);
        $user->addRole($role);

        $this->assertTrue($user->isAllowed(TestPermissionsEnum::HAS_PERMISSION));
        $this->assertTrue($user->isAllowed(TestPermissionsEnum::DOES_NOT_HAVE_PERMISSION));
        $this->assertFalse($user->isAllowed(Common::CAN_DO_NOTHING));
    }
}
