<?php

declare(strict_types=1);

namespace NoahVet\Reef\Test\A_Unit\DependencyInjection;

use NoahVet\Reef\Business\Enumerator\Factory\EstablishmentWithTeamEnumeratorFactory;
use NoahVet\Reef\DependencyInjection\ReefApiClientExtension;
use NoahVet\Reef\Phpunit\RabbitMQ\Consumer\Factory\MockedMQConsumerFactory;
use NoahVet\Reef\Phpunit\RabbitMQ\Producer\Factory\MockedMQProducerFactory;
use NoahVet\Reef\Phpunit\Security\ResourceType\MockedResourceCollectionPermissionFetcher;
use NoahVet\Reef\Phpunit\Security\Voter\MockedIAMVoter;
use NoahVet\Reef\Security\Voter\IAMVoter;
use NoahVet\Reef\Security\Voter\IAMVoterInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\NullAdapter;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

class ReefApiClientExtensionTest extends TestCase
{
    public function testParameters(): void
    {
        $container = new ContainerBuilder();

        $extension = new ReefApiClientExtension();
        $extension->load([[
            'app_name' => 'bsm',
            'url' => 'https://staging.vetinweb.com',
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'oauth_base_url' => 'https://auth.staging.vetinweb.com',
        ]], $container);

        $this->assertSame(
            'bsm',
            $container->getParameter('reef.app_name'),
        );
        $this->assertSame(
            'https://staging.vetinweb.com',
            $container->getParameter('reef.url'),
        );
        $this->assertSame(
            'client_id',
            $container->getParameter('reef.client_id'),
        );
        $this->assertSame(
            'client_secret',
            $container->getParameter('reef.client_secret'),
        );
        $this->assertNull(
            $container->getParameter('reef.service_token'),
        );
    }

    public function testAllServices(): void
    {
        $container = new ContainerBuilder();

        $extension = new ReefApiClientExtension();
        $extension->load([[
            'app_name' => 'bsm',
            'url' => 'https://staging.vetinweb.com',
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'service_token' => 'sample_token',
            'oauth_base_url' => 'https://auth.staging.vetinweb.com',
        ]], $container);

        $registeredServices = [
            \NoahVet\Reef\Command\SyncPoliciesCommand::class,
            \NoahVet\Reef\Factory\ClientFactory::class,
            \NoahVet\Reef\Security\ReefOAuthAuthenticator::class,
            \NoahVet\Reef\Security\Authentication\BearerClientHMacComputer::class,
            \NoahVet\Reef\Security\IAM\Mapper\IAMResourceMapper::class,
            IAMVoter::class,
            EstablishmentWithTeamEnumeratorFactory::class,
            \NoahVet\Reef\Security\ResourceType\ResourceCollectionPermissionFetcher::class,
        ];

        foreach ($registeredServices as $service) {
            $this->assertTrue(
                $container->hasDefinition($service),
                $service.' is defined',
            );
        }

        $permissionFetcherAlias = $container->getAlias(
            \NoahVet\Reef\Security\ResourceType\ResourceCollectionPermissionFetcherInterface::class,
        );
        self::assertSame(
            \NoahVet\Reef\Security\ResourceType\ResourceCollectionPermissionFetcher::class,
            (string) $permissionFetcherAlias,
        );
    }

    public function testTestServices(): void
    {
        $parameterBag = new ParameterBag();
        $parameterBag->add(['kernel.environment' => 'test']);

        $container = new ContainerBuilder($parameterBag);

        $extension = new ReefApiClientExtension();
        $extension->load([[
            'app_name' => 'bsm',
            'url' => 'https://staging.vetinweb.com',
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'service_token' => 'sample_token',
            'oauth_base_url' => 'https://auth.staging.vetinweb.com',
        ]], $container);

        $iamVoterAlias = $container->getAlias(IAMVoter::class);
        self::assertSame(
            MockedIAMVoter::class,
            (string) $iamVoterAlias,
        );

        $iamVoterInterfaceAlias = $container->getAlias(
            IAMVoterInterface::class,
        );
        self::assertSame(
            MockedIAMVoter::class,
            (string) $iamVoterInterfaceAlias,
        );

        $permissionFetcherAlias = $container->getAlias(
            \NoahVet\Reef\Security\ResourceType\ResourceCollectionPermissionFetcherInterface::class,
        );
        self::assertSame(
            MockedResourceCollectionPermissionFetcher::class,
            (string) $permissionFetcherAlias,
        );

        $mqConsumerFactoryAlias = $container->getAlias(
            \NoahVet\Reef\RabbitMQ\Consumer\Factory\ReefMQConsumerFactoryInterface::class,
        );
        self::assertSame(
            MockedMQConsumerFactory::class,
            (string) $mqConsumerFactoryAlias,
        );

        $mqProducerFactoryAlias = $container->getAlias(
            \NoahVet\Reef\RabbitMQ\Producer\Factory\ReefMQProducerFactoryInterface::class,
        );
        self::assertSame(
            MockedMQProducerFactory::class,
            (string) $mqProducerFactoryAlias,
        );
    }

    public function testServiceTokenServicesNotDefined(): void
    {
        $parameterBag = new ParameterBag();
        $parameterBag->add(['kernel.environment' => 'test']);

        $container = new ContainerBuilder($parameterBag);

        $extension = new ReefApiClientExtension();
        $extension->load([[
            'app_name' => 'bsm',
            'url' => 'https://staging.vetinweb.com',
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'service_token' => null,
            'oauth_base_url' => 'https://auth.staging.vetinweb.com',
        ]], $container);

        $registeredServices = [
            'reef.client.service',
            \NoahVet\Reef\Business\Enumerator\EstablishmentWithTeamEnumerator::class,
            \NoahVet\Reef\Business\Enumerator\GroupWithTeamEnumerator::class,
        ];

        foreach ($registeredServices as $service) {
            $this->assertFalse(
                $container->hasDefinition($service),
                $service.' is not defined',
            );
        }
    }

    public function testServiceTokenServices(): void
    {
        $parameterBag = new ParameterBag();
        $parameterBag->add(['kernel.environment' => 'test']);

        $container = new ContainerBuilder($parameterBag);

        $extension = new ReefApiClientExtension();
        $extension->load([[
            'app_name' => 'bsm',
            'url' => 'https://staging.vetinweb.com',
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'service_token' => 'sample_token',
            'oauth_base_url' => 'https://auth.staging.vetinweb.com',
        ]], $container);

        $registeredServices = [
            'reef.client.service',
            \NoahVet\Reef\Business\Enumerator\EstablishmentWithTeamEnumerator::class,
            \NoahVet\Reef\Business\Enumerator\GroupWithTeamEnumerator::class,
        ];

        foreach ($registeredServices as $service) {
            $this->assertTrue(
                $container->hasDefinition($service),
                $service.' is defined',
            );
        }
    }
    /*
        public function testCacheServiceFound(): void
        {
            $container = new ContainerBuilder();

            $cacheService = new NullAdapter();

            $container->set('cache.app', $cacheService);

            $extension = new ReefApiClientExtension();
            $extension->load([[
                'app_name' => 'bsm',
                'url' => 'https://staging.vetinweb.com',
                'client_id' => 'client_id',
                'client_secret' => 'client_secret',
                'cache_service' => 'cache.app',
                'oauth_base_url' => 'https://auth.staging.vetinweb.com',
            ]], $container);

            $definition = $container->getDefinition(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);
            $definition->setPublic(true);

            $container->compile();

            /** @var \NoahVet\Reef\Security\ReefOAuthAuthenticator $authenticator */
    /*
        $authenticator = $container->get(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);

        self::assertSame($cacheService, $authenticator->getCache());
    }
    */
    /*
        public function testCacheServiceNotFound(): void
        {
            $container = new ContainerBuilder();

            $extension = new ReefApiClientExtension();
            $extension->load([[
                'app_name' => 'bsm',
                'url' => 'https://staging.vetinweb.com',
                'client_id' => 'client_id',
                'client_secret' => 'client_secret',
                'cache_service' => 'cache.app',
                'oauth_base_url' => 'https://auth.staging.vetinweb.com',
            ]], $container);

            $definition = $container->getDefinition(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);
            $definition->setPublic(true);

            $container->compile();

            /** @var \NoahVet\Reef\Security\ReefOAuthAuthenticator $authenticator */
    /*
        $authenticator = $container->get(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);

        self::assertNull($authenticator->getCache());
    }
    */
    /*
        public function testCacheServiceNotDefined(): void
        {
            $container = new ContainerBuilder();

            $extension = new ReefApiClientExtension();
            $extension->load([[
                'app_name' => 'bsm',
                'url' => 'https://staging.vetinweb.com',
                'client_id' => 'client_id',
                'client_secret' => 'client_secret',
                'oauth_base_url' => 'https://auth.staging.vetinweb.com',
            ]], $container);

            $definition = $container->getDefinition(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);
            $definition->setPublic(true);

            $container->compile();

            /** @var \NoahVet\Reef\Security\ReefOAuthAuthenticator $authenticator */
    /*
        $authenticator = $container->get(\NoahVet\Reef\Security\ReefOAuthAuthenticator::class);

        self::assertNull($authenticator->getCache());
    }
    */
}
