<?php


namespace AutoAdmin\Bundle\Content\Provider;


use AutoAdmin\Bundle\Content\Cache\StaticTranslationCacheHandler;
use AutoAdmin\Bundle\Content\Configuration\ConfigManager;
use AutoAdmin\Bundle\Content\Entity\Locale;
use AutoAdmin\Bundle\Content\Model\LocaleInterface;
use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use Symfony\Contracts\Translation\TranslatorInterface;

class TranslationProvider
{
    protected ?Locale $lockedLocale = null;

    public function __construct(
        protected StaticTranslationCacheHandler $cacheHandler,
        protected SiteContextHelper $siteContextHelper,
        protected TranslatorInterface $translator,
        protected ConfigManager $contentConfig,
        protected string $appEnv,
    ) {
    }

    public function translate($key, $domain = 'messages', $options = [], mixed $forceLocale = null): ?string
    {
        $translations = $this->cacheHandler->getValue();

        if ($this->lockedLocale) {
            $locale = $this->lockedLocale->getCode();
        } elseif ($forceLocale) {
            $locale = $forceLocale;
        } else {
            $locale = $this->siteContextHelper->getCurrentContext()->getLocale()->getCode();
        }

        $siteSlug = $this->siteContextHelper->getCurrentContext()->getSite()->getSlug();

        $value = null;
        if (!empty($translations[$siteSlug][$locale][$domain][$key])) {
            $value = $translations[$siteSlug][$locale][$domain][$key];
            foreach ($options as $optKey => $optVal) {
                if (str_starts_with($optKey, '%') && str_ends_with($optKey, '%')) {
                    $value = str_replace($optKey, $optVal, $value);
                }
            }
        }

        $staticTransCfg = $this->contentConfig->getConfig('static_translation');
        $isDebug = !empty($staticTransCfg['debug']) && $staticTransCfg['debug'] === true;

        if ($this->appEnv === 'dev' && $isDebug && $value === null) {
            $hasFallback = $this->translator->trans($key, $options, $domain);

            return $key.':'.$domain.':'.($hasFallback ? 'OK' : 'KO');
        }

        if (empty($value)) {
            $value = $this->translator->trans($key, $options, $domain, $locale);
        }

        return $value;
    }

    public function lockLocale(mixed $locale): ?Locale
    {
        if (is_string($locale)) {
            $matchingLocale = $this->siteContextHelper->getSiteLocaleForCode($locale);
            if ($matchingLocale instanceof LocaleInterface) {
                $this->lockedLocale = $matchingLocale;
            } else {
                $site = $this->siteContextHelper->getCurrentContext()->getSite();
                throw new \InvalidArgumentException('Invalid locale asked for site: '.$site->getSlug());
            }
        } elseif ($locale instanceof Locale) {
            $this->lockedLocale = $locale;
        } else {
            throw new \InvalidArgumentException('Invalid locale type');
        }

        return $this->lockedLocale;
    }

    public function unlockLocale(): void
    {
        $this->lockedLocale = null;
    }
}
