<?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 Doctrine\Persistence\ManagerRegistry;
use RuntimeException;

class SiteContextHelper
{
    private ?SiteContext $siteContext;

    public function __construct(
        private ManagerRegistry $doctrine,
        private EntityTranslator $entityTranslator
    ) {
        $this->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->entityTranslator->setLocale($locale);
    }

    /**
     * @return SiteConfig[]
     */
    public function getAllSiteConfigs(bool $enabled = true): array
    {
        /** @var Site[] $sites */
        $sites = $this->doctrine->getRepository(Site::class)->findAll();
        $siteConfigs = [];
        foreach ($sites as $site) {
            $siteConfigs = $this->getSiteLocalizedDomains($site, $siteConfigs);
        }

        return $siteConfigs;
    }

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

    /**
     * @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.');
            }
        }

        $found = null;

        /** @var Domain $domain */
        foreach ($site->getDomains() as $domain) {
            /** @var LocaleInterface $locale */
            foreach ($domain->getLocales() as $locale) {
                if ($locale->getCode() == $locale->getCode()) {
                    $found = $domain;
                    break 2;
                }
            }
        }

        return $found;
    }

    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->getSiteLocalizedDomains($this->siteContext->getSite()) as $siteConfig) {
            if ($siteConfig->getLocale()->getCode() === $localeCode) {
                return $siteConfig->getLocale();
            }
        }

        return null;
    }

}
