<?php

namespace MintyPHP\Tests\Unit\Module;

use MintyPHP\Module\AddressBook\AddressBookAuthorizationPolicy;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Tests\Service\Access\AuthorizationPolicyTestSupport;
use PHPUnit\Framework\TestCase;

/**
 * @covers \MintyPHP\Module\AddressBook\AddressBookAuthorizationPolicy
 */
final class AddressBookAuthorizationPolicyTest extends TestCase
{
    use AuthorizationPolicyTestSupport;

    public function testSupportsOwnAbility(): void
    {
        $policy = new AddressBookAuthorizationPolicy($this->createMock(PermissionService::class));
        self::assertTrue($policy->supports(AddressBookAuthorizationPolicy::ABILITY_VIEW));
    }

    public function testDoesNotSupportOtherAbilities(): void
    {
        $policy = new AddressBookAuthorizationPolicy($this->createMock(PermissionService::class));
        self::assertFalse($policy->supports('ops.admin.jobs.view'));
        self::assertFalse($policy->supports(''));
        self::assertFalse($policy->supports('ops.address_book.view')); // old ability string
    }

    public function testAllowedWithPermission(): void
    {
        $permissionService = $this->permissionGatewayAllowing([
            5 => [AddressBookAuthorizationPolicy::PERMISSION_KEY],
        ]);

        $policy = new AddressBookAuthorizationPolicy($permissionService);
        $decision = $policy->authorize(AddressBookAuthorizationPolicy::ABILITY_VIEW, [
            'actor_user_id' => 5,
        ]);

        self::assertTrue($decision->isAllowed());
    }

    public function testDeniedWithoutPermission(): void
    {
        $permissionService = $this->permissionGatewayAllowing([5 => []]);

        $policy = new AddressBookAuthorizationPolicy($permissionService);
        $decision = $policy->authorize(AddressBookAuthorizationPolicy::ABILITY_VIEW, [
            'actor_user_id' => 5,
        ]);

        $this->assertForbiddenDecision($decision);
    }

    public function testDeniedWithZeroActorId(): void
    {
        $permissionService = $this->createMock(PermissionService::class);
        $permissionService->expects($this->never())->method('userHas');

        $policy = new AddressBookAuthorizationPolicy($permissionService);
        $decision = $policy->authorize(AddressBookAuthorizationPolicy::ABILITY_VIEW, [
            'actor_user_id' => 0,
        ]);

        $this->assertForbiddenDecision($decision);
    }

    public function testDeniedWithMissingActorId(): void
    {
        $permissionService = $this->createMock(PermissionService::class);
        $permissionService->expects($this->never())->method('userHas');

        $policy = new AddressBookAuthorizationPolicy($permissionService);
        $decision = $policy->authorize(AddressBookAuthorizationPolicy::ABILITY_VIEW, []);

        $this->assertForbiddenDecision($decision);
    }
}
