<?php

declare(strict_types=1);

namespace NoahVet\Reef\Test\A_Unit\Phpunit\ResourceType;

use NoahVet\Reef\Exception\NoBearerTokenException;
use NoahVet\Reef\Exception\PermissionFetchException;
use NoahVet\Reef\Phpunit\Fixture\FixtureRepository;
use NoahVet\Reef\Phpunit\Fixture\PermissionFixture;
use NoahVet\Reef\Phpunit\Fixture\ReefTokenFixture;
use NoahVet\Reef\Phpunit\Security\ResourceType\MockedResourceCollectionPermissionFetcher;
use NoahVet\Reef\Security\IAM\Model\Resource;
use NoahVet\Reef\Security\IAM\Model\ResourceGroupWithMembers;
use NoahVet\Reef\Security\IAM\Model\ResourceType;
use NoahVet\Reef\Security\User\ReefOAuthUser;
use PHPUnit\Framework\TestCase;

class MockedResourceCollectionPermissionFetcherTest extends TestCase
{
    public function testFetchOk(): void
    {
        $user = new ReefOAuthUser('toto', null);
        $resourceType = ResourceType::fromString('reef:phpunit:ResourceType');
        $permissions = [
            new PermissionFixture(
                Resource::fromString('reef:phpunit:unkownType', 'id0'),
                ['permission_unkown'],
            ),
            new PermissionFixture(
                ResourceGroupWithMembers::fromStringWithMembers($resourceType, '*', []),
                ['permission_read'],
            ),
            new PermissionFixture(
                ResourceGroupWithMembers::fromStringWithMembers(
                    $resourceType,
                    'idg1',
                    [
                        'idr2',
                    ],
                ),
                ['permission_read', 'permission_write'],
            ),
            new PermissionFixture(
                Resource::fromString($resourceType, 'idr1'),
                ['permission_read', 'permission_write'],
            ),
        ];

        $tokenFixture = new ReefTokenFixture(
            'unit_token',
            $user,
            $permissions,
            false,
        );

        $repository = new FixtureRepository();
        $repository->addFixture($tokenFixture);

        $fetcher = new MockedResourceCollectionPermissionFetcher(
            null,
            $repository,
        );

        $permissionCollection = $fetcher->fetch(
            $resourceType,
            false,
            'unit_token',
        );
        self::assertEquals(['permission_read'], $permissionCollection->getAllPermissions());
        self::assertEquals(
            ['idg1' => ['permission_read', 'permission_write']],
            $permissionCollection->getGroupPermissions(),
        );
        self::assertEquals(
            ['idr1' => ['permission_read', 'permission_write']],
            $permissionCollection->getResourcePermissions(),
        );

        $permissionCollection = $fetcher->fetch(
            $resourceType,
            true,
            'unit_token',
        );
        self::assertEquals(['permission_read'], $permissionCollection->getAllPermissions());
        self::assertEquals(
            [
                'idr1' => ['permission_read', 'permission_write'],
                'idr2' => ['permission_read', 'permission_write'],
            ],
            $permissionCollection->getResourcePermissions(),
        );
    }

    public function testFetchNotToken(): void
    {
        $repository = new FixtureRepository();

        $fetcher = new MockedResourceCollectionPermissionFetcher(
            null,
            $repository,
        );

        self::expectException(NoBearerTokenException::class);

        $fetcher->fetch(
            ResourceType::fromString('reef:phpunit:ResourceType'),
        );
    }

    public function testFetchInvalidToken(): void
    {
        $repository = new FixtureRepository();

        $fetcher = new MockedResourceCollectionPermissionFetcher(
            null,
            $repository,
        );

        self::expectException(PermissionFetchException::class);

        $fetcher->fetch(
            ResourceType::fromString('reef:phpunit:ResourceType'),
            true,
            'unit_token',
        );
    }
}
