<?php

namespace NoahVet\Reef\Test\A_Unit\Infrastructure\Security\IAM\Mapper;

use NoahVet\Reef\Domain\Security\Model\Resource;
use NoahVet\Reef\Infrastructure\Security\IAM\Mapper\IAMResourceMapper;
use NoahVet\Reef\Infrastructure\Security\IAM\Mapper\InternalResourceMapperInterface;
use PHPUnit\Framework\TestCase;

class IAMResourceMapperTest extends TestCase
{
    public function testFirstMatchingMapperResultIsReturned(): void
    {
        $resource = Resource::fromString('reef:phpunit:resource', 'test-id');
        $subject = new \stdClass();

        $mapper1 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper1->method('canMap')->willReturn(true);
        $mapper1->method('mapResource')->willReturn($resource);

        $mapper2 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper2->expects(self::never())->method('canMap');

        $iam = new IAMResourceMapper([$mapper1, $mapper2]);

        self::assertSame($resource, $iam->map($subject));
    }

    public function testReturnsNullWhenNoMapperMatches(): void
    {
        $subject = new \stdClass();

        $mapper1 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper1->method('canMap')->willReturn(false);

        $mapper2 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper2->method('canMap')->willReturn(false);

        $iam = new IAMResourceMapper([$mapper1, $mapper2]);

        self::assertNull($iam->map($subject));
    }

    public function testOnlyFirstMatchingMapperIsUsed(): void
    {
        $resource1 = Resource::fromString('reef:phpunit:resource', 'first');
        $resource2 = Resource::fromString('reef:phpunit:resource', 'second');
        $subject = new \stdClass();

        $mapper1 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper1->method('canMap')->willReturn(true);
        $mapper1->method('mapResource')->willReturn($resource1);

        $mapper2 = $this->createMock(InternalResourceMapperInterface::class);
        $mapper2->expects(self::never())->method('canMap');
        $mapper2->expects(self::never())->method('mapResource');

        $iam = new IAMResourceMapper([$mapper1, $mapper2]);

        self::assertSame($resource1, $iam->map($subject));
    }
}
