<?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\Settings;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\CoreBundle\Entity\PageConfig;
use Ferienpass\CoreBundle\Tenant\TenantContext;
use Psr\Cache\CacheItemPoolInterface;

class PageConfigManager
{
    private const CACHE_KEY_PAGE_CONFIG = 'ferienpass.page_config';

    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly CacheItemPoolInterface $appConfigCache,
        private readonly TenantContext $tenantContext,
    ) {
    }

    public function getPageConfig(): PageConfig
    {
        // No tenant on a multi-tenant build means the query is unfiltered, and
        // `findOneBy([])` would answer with whichever municipality's row comes
        // first — its name, its colours, its sender address. The platform
        // console reaches this before anyone has signed in; it gets the
        // defaults instead.
        if ($this->tenantContext->isEnabled() && null === $this->tenantContext->getTenant()) {
            return new PageConfig();
        }

        $item = $this->appConfigCache->getItem($this->tenantContext->cacheKey(self::CACHE_KEY_PAGE_CONFIG));
        if ($item->isHit()) {
            return $item->get();
        }

        $config = $this->entityManager->getRepository(PageConfig::class)->findOneBy([]) ?? new PageConfig();

        $item->set($config);
        $this->appConfigCache->save($item);

        return $config;
    }

    /**
     * The managed entity for a screen that is about to modify and save it.
     *
     * {@see getPageConfig()} may answer from the cache, and a cache-
     * unserialized config is detached from the entity manager — persisting it
     * would insert a second row (or trip over its equally detached tenant
     * reference) instead of updating the existing one.
     */
    public function getPageConfigForUpdate(): PageConfig
    {
        if ($this->tenantContext->isEnabled() && null === $this->tenantContext->getTenant()) {
            throw new \LogicException('No tenant is active — there is no page config to update.');
        }

        return $this->entityManager->getRepository(PageConfig::class)->findOneBy([]) ?? new PageConfig();
    }

    public function savePageConfig(PageConfig $config): void
    {
        $this->entityManager->persist($config);
        $this->entityManager->flush();

        $this->appConfigCache->deleteItem($this->tenantContext->cacheKey(self::CACHE_KEY_PAGE_CONFIG));
    }
}
