<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Tests\Settings;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\CoreBundle\Entity\IntegrationConfig;
use Ferienpass\CoreBundle\Entity\IntegrationCredential;
use Ferienpass\CoreBundle\Repository\IntegrationConfigRepository;
use Ferienpass\CoreBundle\Settings\IntegrationsManager;
use PHPUnit\Framework\TestCase;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;

class IntegrationsManagerTest extends TestCase
{
    private $entityManager;
    private $cache;
    private $repository;
    private string $encryptionKey;

    protected function setUp(): void
    {
        if (!class_exists(\ParagonIE\Halite\Symmetric\Crypto::class)) {
            self::markTestSkipped('paragonie/halite is missing');
        }

        $this->entityManager = $this->createMock(EntityManagerInterface::class);
        $this->cache = $this->createStub(CacheItemPoolInterface::class);
        $this->repository = $this->createStub(IntegrationConfigRepository::class);
        $this->encryptionKey = bin2hex(random_bytes(16));

        $this->entityManager->method('getRepository')->with(IntegrationConfig::class)->willReturn($this->repository);
    }

    public function testOpenAiApiKeyPrecedence(): void
    {
        $cacheItem = $this->createStub(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(false);
        $this->cache->method('getItem')->willReturn($cacheItem);

        $manager = new IntegrationsManager(
            $this->entityManager,
            $this->cache,
            'dev',
            $this->encryptionKey,
            'sk-env-key'
        );

        $this->assertTrue($manager->isOpenAiApiKeyFromEnv());
        $this->assertTrue($manager->isIntegrationConfigured('gpt_image_generation'));

        $config = $manager->getIntegrationConfig('gpt_image_generation');
        $this->assertSame('sk-env-key', $config['OPENAI_API_KEY']);
    }

    public function testBrevoSmsApiKeyFromEnvPrecedence(): void
    {
        $cacheItem = $this->createStub(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(false);
        $this->cache->method('getItem')->willReturn($cacheItem);

        $manager = new IntegrationsManager(
            $this->entityManager,
            $this->cache,
            'dev',
            $this->encryptionKey,
            null, // openai api key
            'brevo-env-key'
        );

        $this->assertTrue($manager->isBrevoSmsApiKeyFromEnv());
        $config = $manager->getIntegrationConfig('brevo_sms');
        $this->assertSame('brevo-env-key', $config['BREVO_API_KEY']);
    }

    public function testIntegrationConfigLoadingWithDecryption(): void
    {
        $cacheItem = $this->createStub(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(false);
        $this->cache->method('getItem')->willReturn($cacheItem);

        $manager = new IntegrationsManager(
            $this->entityManager,
            $this->cache,
            'dev',
            $this->encryptionKey
        );

        $integrationConfig = new IntegrationConfig('pm_payment');
        $integrationConfig->setConfig(['base_url' => 'https://example.com']);

        $credential = new IntegrationCredential('dev');
        $credential->setConfig([
            'api_key' => $manager->encrypt('secret-key'),
        ]);
        $integrationConfig->addCredential($credential);

        $this->repository->method('findOneBy')->willReturn($integrationConfig);

        $config = $manager->getIntegrationConfig('pm_payment');

        $this->assertSame('https://example.com', $config['base_url']);
        $this->assertSame('secret-key', $config['api_key']);
    }

    public function testIsIntegrationConfigured(): void
    {
        $cacheItem = $this->createStub(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(false);
        $this->cache->method('getItem')->willReturn($cacheItem);

        $manager = new IntegrationsManager(
            $this->entityManager,
            $this->cache,
            'prod',
            $this->encryptionKey
        );

        $integrationConfig = new IntegrationConfig('pm_payment');
        $credentialDev = new IntegrationCredential('dev');
        $integrationConfig->addCredential($credentialDev);

        $this->repository->method('findOneBy')->willReturn($integrationConfig);

        // Not configured for prod
        $this->assertFalse($manager->isIntegrationConfigured('pm_payment'));

        $credentialProd = new IntegrationCredential('prod');
        $credentialProd->setConfig(['api_key' => 'secret-prod']);
        $integrationConfig->addCredential($credentialProd);

        // Now configured for prod
        $this->assertTrue($manager->isIntegrationConfigured('pm_payment'));
    }
}
