<?php
namespace Szurubooru\Tests\Services;
use Szurubooru\Entities\User;
use Szurubooru\Privilege;
use Szurubooru\Services\AuthService;
use Szurubooru\Services\PrivilegeService;
use Szurubooru\Tests\AbstractTestCase;

final class PrivilegeServiceTest extends AbstractTestCase
{
    private $configMock;
    private $authServiceMock;

    public function setUp()
    {
        parent::setUp();
        $this->configMock = $this->mockConfig();
        $this->authServiceMock = $this->mock(AuthService::class);
    }

    public function testReadingConfig()
    {
        $testUser = new User();
        $testUser->setName('dummy');
        $testUser->setAccessRank(User::ACCESS_RANK_POWER_USER);
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser);

        $privilege = Privilege::LIST_USERS;
        $this->configMock->set('security/privileges/' . $privilege, 'powerUser');

        $privilegeService = $this->getPrivilegeService();
        $this->assertEquals([$privilege], $privilegeService->getCurrentPrivileges());
        $this->assertTrue($privilegeService->hasPrivilege($privilege));
    }

    public function testIsLoggedInByNameString()
    {
        $testUser1 = new User();
        $testUser1->setName('dummy');
        $testUser2 = new User();
        $testUser2->setName('godzilla');
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser1);

        $privilegeService = $this->getPrivilegeService();
        $this->assertTrue($privilegeService->isLoggedIn($testUser1->getName()));
        $this->assertFalse($privilegeService->isLoggedIn($testUser2->getName()));
    }

    public function testIsLoggedInByEmailString()
    {
        $testUser1 = new User();
        $testUser1->setName('user1');
        $testUser1->setEmail('dummy');
        $testUser2 = new User();
        $testUser2->setName('user2');
        $testUser2->setEmail('godzilla');
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser1);

        $privilegeService = $this->getPrivilegeService();
        $this->assertTrue($privilegeService->isLoggedIn($testUser1->getEmail()));
        $this->assertFalse($privilegeService->isLoggedIn($testUser2->getEmail()));
    }

    public function testIsLoggedInByUserId()
    {
        $testUser1 = new User(5);
        $testUser2 = new User(13);
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser1);

        $privilegeService = $this->getPrivilegeService();
        $this->assertTrue($privilegeService->isLoggedIn($testUser1));
        $this->assertFalse($privilegeService->isLoggedIn($testUser2));
    }

    public function testIsLoggedInByUserName()
    {
        $testUser1 = new User();
        $testUser1->setName('dummy');
        $testUser2 = new User();
        $testUser2->setName('godzilla');
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser1);

        $privilegeService = $this->getPrivilegeService();
        $this->assertFalse($privilegeService->isLoggedIn($testUser1));
        $this->assertFalse($privilegeService->isLoggedIn($testUser2));
    }

    public function testIsLoggedInByInvalidObject()
    {
        $testUser = new User();
        $testUser->setName('dummy');
        $this->authServiceMock->expects($this->atLeastOnce())->method('getLoggedInUser')->willReturn($testUser);

        $rubbish = new \StdClass;
        $privilegeService = $this->getPrivilegeService();
        $this->setExpectedException(\InvalidArgumentException::class);
        $this->assertTrue($privilegeService->isLoggedIn($rubbish));
    }

    private function getPrivilegeService()
    {
        return new PrivilegeService(
            $this->configMock,
            $this->authServiceMock);
    }
}