<?php

namespace KupShop\KupShopBundle\Views\Traits;

use KupShop\ComponentsBundle\View\ComponentsViewInterface;
use KupShop\KupShopBundle\Util\Compat\CtrlLoader;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use Symfony\Contracts\Service\Attribute\Required;
use Twig\Environment;
use Twig\TemplateWrapper;

if (!findModule(\Modules::COMPONENTS)) {
    trait TemplateTrait
    {
        // Base
        /**
         * @var \Smarty
         */
        protected $smarty;
        protected bool $useAdminSmarty = false;

        protected array $templateVariables = [];

        /** @var string Template file to use */
        protected $template;

        public function getSmarty()
        {
            if (!is_null($this->smarty)) {
                return $this->smarty;
            }

            $this->smarty = createSmarty($this->useAdminSmarty, true);

            return $this->smarty;
        }

        public function render()
        {
            return $this->getSmarty()->assign($this->templateVariables)->fetch($this->getTemplate());
        }

        public function renderToOutput()
        {
            $this->getSmarty()->assign($this->templateVariables)->display($this->getTemplate());
        }

        public function getTemplate()
        {
            if ($this->template) {
                return $this->template;
            }

            throw new \Exception('Undefined template');
        }

        public function setTemplate(string $template)
        {
            $this->template = $template;

            return $this;
        }

        public function getTemplateVariables()
        {
            return [];
        }

        public function addTemplateVariables($array)
        {
            $this->templateVariables = [$this->templateVariables, ...$array];
        }

        public function setSmartyFallback(string $smartyFallback): self
        {
            // Ignore without components
            return $this;
        }
    }
} else {
    trait TemplateTrait
    {
        protected Environment $twig;

        /** @var string Template file to use */
        protected $template;

        protected string $smartyFallback;
        protected bool $useAdminSmarty = false;

        protected array $templateVariables = [];

        public function render(): string
        {
            return $this->twig->render($this->getTwigTemplate(), $this->templateVariables);
        }

        public function renderToOutput(): void
        {
            $this->twig->display($this->getTwigTemplate(), $this->templateVariables);
        }

        protected function getTwigTemplate(): TemplateWrapper
        {
            $template = $this->getTemplate();

            // Pokud používám jako šablonu .tpl soubor, předpokládám, že sem v hlavním view abych byl BC compatible.
            // Pokud už mám šablonu s .html.twig, mám novej kód už bych tam měl mít správně ten top-level folder podle nové struktury
            if (!str_ends_with($template, '.html.twig')) {
                $template = 'view/'.$template;
            }

            $templates = [preg_replace('/\.tpl$/', '.html.twig', $template)];

            $fallback = $this->getSmartyFallback();
            if ($fallback) {
                $templates[] = $fallback;
            }

            return $this->twig->resolveTemplate($templates);
        }

        public function getTemplate()
        {
            if ($this->template) {
                return $this->template;
            }

            throw new \Exception('Undefined template');
        }

        public function setTemplate(string $template): self
        {
            $this->template = $template;

            return $this;
        }

        public function getTemplateVariables(): array
        {
            return [];
        }

        public function addTemplateVariables($array): void
        {
            $this->templateVariables = [$this->templateVariables, ...$array];
        }

        #[Required]
        public function setTwig(Environment $twig): self
        {
            $this->twig = $twig;

            return $this;
        }

        public function renderUsingSmarty(): string
        {
            $this->templateVariables['ctrl'] = ServiceContainer::getService(CtrlLoader::class);

            return createSmarty($this->useAdminSmarty, true)->assign($this->templateVariables)->fetch($this->getTemplate());
        }

        public function isComponentsView(): bool
        {
            return $this instanceof ComponentsViewInterface;
        }

        protected function getSmartyFallback(): ?string
        {
            if ($this->isComponentsView()) {
                return null;
            }

            if (!isset($this->smartyFallback)) {
                return 'Případně si povol fallback přes $smartyFallback v '.get_class($this);
            }

            return "smarty_fallback/{$this->smartyFallback}.html.twig";
        }

        public function setSmartyFallback(string $smartyFallback): self
        {
            $this->smartyFallback = $smartyFallback;

            return $this;
        }
    }
}
