<?php


namespace AutoAdmin\Bundle\Content\Site;


use AutoAdmin\Bundle\Content\Context\SiteContext;
use AutoAdmin\Bundle\Content\Entity\Domain;
use AutoAdmin\Bundle\Content\Entity\Locale;
use AutoAdmin\Bundle\Content\Entity\Site;
use AutoAdmin\Bundle\Content\Model\LocaleInterface;
use AutoAdmin\Bundle\Content\Model\SiteConfig;
use AutoAdmin\Bundle\Content\Translation\EntityTranslator;
use RuntimeException;

class SiteContextHelper
{
    public function __construct(
        private EntityTranslator $entityTranslator,
        private SiteConfigBuilderHelper $siteConfigBuilder,
        private ?SiteContext $siteContext = null
    ) {
    }

    public function loadSiteAndLocale(Site $site, Locale $locale): void
    {
        $this->applySiteAndLocale($site, $locale);
    }

    public function loadSiteConfig(SiteConfig $siteConfig): void
    {
        $this->applySiteAndLocale($siteConfig->getSite(), $siteConfig->getLocale());
    }

    public function loadContext(SiteContext $siteContext): void
    {
        $this->applySiteAndLocale($siteContext->getSite(), $siteContext->getLocale());
    }

    protected function applySiteAndLocale(Site $site, Locale $locale): void
    {
        $this->siteContext = new SiteContext();
        $this->siteContext->setSite($site);
        $this->siteContext->setLocale($locale);
        $this->siteContext->setDomain($this->siteConfigBuilder->getDomain($site, $locale));

        $this->entityTranslator->setLocale($locale);
    }

    /**
     * @return SiteConfig[]
     */
    public function getAllSiteConfigs(bool $enabled = true): array
    {
        return $this->siteConfigBuilder->buildAllSitesConfigs();
    }

    /**
     * @return SiteConfig[]
     */
    public function getSiteConfigs(Site $site): array
    {
        return $this->siteConfigBuilder->buildSiteConfigs($site);
    }

    /**
     * @return SiteConfig[]
     */
    public function getCurrentContextSiteConfigs(): array
    {
        return $this->siteConfigBuilder->buildSiteConfigs($this->siteContext->getSite());
    }

    /**
     * @deprecated use {@see getSiteConfigs}
     * @return SiteConfig[]
     */
    public function getSiteLocalizedDomains(Site $site = null, array $tab = null): array
    {
        if ($site === null) {
            $site = $this->siteContext->getSite();
            if ($site === null) {
                throw new RuntimeException('Site is not defined, cannot get site autonomously.');
            }
        }

        $tab = $tab ?? [];

        /** @var Domain $domain */
        foreach ($site->getDomains() as $domain) {
            /** @var Locale $locale */
            foreach ($domain->getLocales() as $locale) {
                $tab[] = new SiteConfig($site, $domain, $locale);
            }
        }

        return $tab;
    }

    public function getDomainByLocale(Site $site, LocaleInterface $locale = null): ?Domain
    {
        if ($locale === null) {
            $locale = $this->getCurrentContext()->getLocale();
            if ($locale === null) {
                throw new RuntimeException('Locale is not defined, cannot get locale autonomously.');
            }
        }

        $siteConfig = $this->siteConfigBuilder->getSiteConfigByLocale($site, $locale);
        return $siteConfig?->getDomain();
    }

    public function getCurrentContext(): ?SiteContext
    {
        return $this->siteContext;
    }

    public function validateCurrentContext(bool $throw = false)
    {
        $valid = $this->siteContext->getSite() !== null
            && $this->siteContext->getLocale() !== null;

        if (!$valid && $throw) {
            throw new \Exception('SiteContext is not loaded.');
        }

        return $valid;
    }

    public function getLocale(): ?Locale
    {
        return $this->siteContext?->getLocale();
    }

    public function getDomain(): ?Domain
    {
        return $this->getDomainByLocale($this->siteContext->getSite(), $this->siteContext->getLocale());
    }

    public function getSite(): ?Site
    {
        return $this->siteContext?->getSite();
    }

    public function getSiteLocaleForCode(string $localeCode): ?LocaleInterface
    {
        foreach ($this->getSiteConfigs($this->siteContext->getSite()) as $siteConfig) {
            if ($siteConfig->getLocale()->getCode() === $localeCode) {
                return $siteConfig->getLocale();
            }
        }

        return null;
    }

    public function isMultilingual(): bool
    {
        return count($this->getDomain()->getLocales()) > 1;
    }
}
