<?php

declare(strict_types=1);

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

use NoahVet\Reef\Jane\Client;
use NoahVet\Reef\Jane\Exception\BadRequestException;
use NoahVet\Reef\Security\IAM\Model\Resource;
use NoahVet\Reef\Security\IAM\ResourceManager;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\HttpFoundation\Response;

class ResourceManagerTest extends TestCase
{
    public function testRegisterResource200(): void
    {
        $client = $this->getMockBuilder(Client::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $endpointParameters = new \NoahVet\Reef\Jane\Endpoint\PostResourceCollection(
            (new \NoahVet\Reef\Jane\Model\Resource())
                ->setSlug('reef:phpunit:resourceType:resourceId')
                ->setResourceType('/api/resource_types/reef:phpunit:resourceType'),
        );
        $responseMock = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $responseMock->method('getStatusCode')
            ->willReturn(Response::HTTP_OK)
        ;

        $client
            ->method('executeRawEndpoint')
            ->with($endpointParameters)
            ->willReturn($responseMock)
        ;

        $resourceManager = new ResourceManager($client);

        $resource = Resource::fromString('reef:phpunit:resourceType', 'resourceId');

        $ret = $resourceManager->registerResource($resource);
        self::assertInstanceOf(ResourceManager::class, $ret);
    }

    public function testRegisterResource201(): void
    {
        $client = $this->getMockBuilder(Client::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $endpointParameters = new \NoahVet\Reef\Jane\Endpoint\PostResourceCollection(
            (new \NoahVet\Reef\Jane\Model\Resource())
                ->setSlug('reef:phpunit:resourceType:resourceId')
                ->setResourceType('/api/resource_types/reef:phpunit:resourceType'),
        );
        $responseMock = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $responseMock->method('getStatusCode')
            ->willReturn(Response::HTTP_CREATED)
        ;

        $client
            ->method('executeRawEndpoint')
            ->with($endpointParameters)
            ->willReturn($responseMock)
        ;

        $resourceManager = new ResourceManager($client);

        $resource = Resource::fromString('reef:phpunit:resourceType', 'resourceId');

        $ret = $resourceManager->registerResource($resource);
        self::assertInstanceOf(ResourceManager::class, $ret);
    }

    public function testRegisterResource409(): void
    {
        $client = $this->getMockBuilder(Client::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $endpointParameters = new \NoahVet\Reef\Jane\Endpoint\PostResourceCollection(
            (new \NoahVet\Reef\Jane\Model\Resource())
                ->setSlug('reef:phpunit:resourceType:resourceId')
                ->setResourceType('/api/resource_types/reef:phpunit:resourceType'),
        );
        $responseMock = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $responseMock->method('getStatusCode')
            ->willReturn(Response::HTTP_CONFLICT)
        ;

        $client
            ->method('executeRawEndpoint')
            ->with($endpointParameters)
            ->willReturn($responseMock)
        ;

        $resourceManager = new ResourceManager($client);

        $resource = Resource::fromString('reef:phpunit:resourceType', 'resourceId');

        $ret = $resourceManager->registerResource($resource);
        self::assertInstanceOf(ResourceManager::class, $ret);
    }

    public function testRegisterResourceError(): void
    {
        $client = $this->getMockBuilder(Client::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;

        $endpointParameters = new \NoahVet\Reef\Jane\Endpoint\PostResourceCollection(
            (new \NoahVet\Reef\Jane\Model\Resource())
                ->setSlug('reef:phpunit:resourceType:resourceId')
                ->setResourceType('/api/resource_types/reef:phpunit:resourceType'),
        );
        $responseMock = $this->getMockBuilder(ResponseInterface::class)
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $responseMock->method('getStatusCode')
            ->willReturn(Response::HTTP_INTERNAL_SERVER_ERROR)
        ;

        $client
            ->method('executeRawEndpoint')
            ->with($endpointParameters)
            ->willReturn($responseMock)
        ;

        $resourceManager = new ResourceManager($client);

        $resource = Resource::fromString('reef:phpunit:resourceType', 'resourceId');

        self::expectException(BadRequestException::class);

        $resourceManager->registerResource($resource);
    }
}
