<?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 Doctrine\Persistence\ManagerRegistry;
use Ferienpass\CoreBundle\Entity\PageConfig;
use Ferienpass\CoreBundle\Repository\EntityRepository;
use Ferienpass\CoreBundle\Settings\PageConfigManager;
use Ferienpass\CoreBundle\Tenant\TenantContext;
use PHPUnit\Framework\TestCase;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;

class PageConfigManagerTest extends TestCase
{
    private $entityManager;
    private $cache;
    private $repository;

    protected function setUp(): void
    {
        $this->entityManager = $this->createMock(EntityManagerInterface::class);
        $this->cache = $this->createMock(CacheItemPoolInterface::class);
        $this->repository = $this->createStub(EntityRepository::class);

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

    public function testGetPageConfigWithCacheHit(): void
    {
        $config = new PageConfig();
        $cacheItem = $this->createStub(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(true);
        $cacheItem->method('get')->willReturn($config);

        $this->cache->method('getItem')->with('ferienpass.page_config')->willReturn($cacheItem);

        $manager = new PageConfigManager($this->entityManager, $this->cache, $this->tenantContext());

        $this->assertSame($config, $manager->getPageConfig());
    }

    public function testGetPageConfigWithCacheMissAndDbHit(): void
    {
        $config = new PageConfig();

        $cacheItem = $this->createMock(CacheItemInterface::class);
        $cacheItem->method('isHit')->willReturn(false);
        $cacheItem->expects($this->once())->method('set')->with($config);

        $cachePool = $this->createMock(CacheItemPoolInterface::class);
        $cachePool->method('getItem')->with('ferienpass.page_config')->willReturn($cacheItem);
        $cachePool->expects($this->once())->method('save')->with($cacheItem);

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

        $manager = new PageConfigManager($this->entityManager, $cachePool, $this->tenantContext());

        $this->assertSame($config, $manager->getPageConfig());
    }

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

        $this->cache->method('getItem')->with('ferienpass.page_config')->willReturn($cacheItem);

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

        $manager = new PageConfigManager($this->entityManager, $this->cache, $this->tenantContext());

        $config = $manager->getPageConfig();
        $this->assertInstanceOf(PageConfig::class, $config);
    }

    public function testSavePageConfigClearsCache(): void
    {
        $config = new PageConfig();

        $entityManager = $this->createMock(EntityManagerInterface::class);
        $entityManager->expects($this->once())->method('persist')->with($config);
        $entityManager->expects($this->once())->method('flush');

        $cachePool = $this->createMock(CacheItemPoolInterface::class);
        $cachePool->expects($this->once())->method('deleteItem')->with('ferienpass.page_config');

        $manager = new PageConfigManager($entityManager, $cachePool, $this->tenantContext());
        $manager->savePageConfig($config);
    }

    private function tenantContext(): TenantContext
    {
        // Single-tenant default: no tenant active, so cache keys are unchanged.
        return new TenantContext($this->createStub(ManagerRegistry::class));
    }
}
