<?php

namespace KupShop\KupShopBundle\Context;

use KupShop\KupShopBundle\Util\Contexts;
use KupShop\PricelistBundle\Context\PricelistContext;
use Symfony\Component\HttpFoundation\RequestStack;

class CacheContext
{
    public const TYPE_TEXT = 'text';
    public const TYPE_PRICE = 'price';
    public const TYPE_AVAILABILITY = 'availability';
    public const TYPE_DELIVERY = 'delivery';
    public const TYPE_FULL_PAGE = 'fullPage';

    protected $languageContext;
    protected $currencyContext;
    protected $countryContext;
    protected $contextManager;

    public function __construct(
        LanguageContext $languageContext,
        CurrencyContext $currencyContext,
        CountryContext $countryContext,
        ContextManager $contextManager,
        protected RequestStack $requestStack,
    ) {
        $this->languageContext = $languageContext;
        $this->currencyContext = $currencyContext;
        $this->countryContext = $countryContext;
        $this->contextManager = $contextManager;
    }

    public function getKey(array $types): ?string
    {
        $key = [];

        foreach ($types as $type) {
            $method = 'getKey'.ucfirst($type);

            $value = call_user_func([$this, $method]);

            if (is_array($value)) {
                $key = array_merge($key, $value);
            } elseif ($value === null) {
                // null == Do not cache
                return null;
            }
        }

        return implode('-', $key);
    }

    protected function getKeyText(): ?array
    {
        return [LanguageContext::class => $this->languageContext->getActiveId()];
    }

    protected function getKeyPrice(): ?array
    {
        $key = [
            CurrencyContext::class => $this->currencyContext->getActiveId(),
        ];

        if (findModule(\Modules::OSS_VATS)) {
            $key[CountryContext::class] = $this->countryContext->getActiveId();
        }

        if (findModule(\Modules::PRICELISTS)) {
            $key[PricelistContext::class] = Contexts::get(PricelistContext::class)->getActiveId();
        }

        return $key;
    }

    protected function getKeyAvailability(): ?array
    {
        return [];
    }

    protected function getKeyDelivery(): ?array
    {
        $key = [
            CurrencyContext::class => $this->currencyContext->getActiveId(),
        ];

        if (findModule(\Modules::OSS_VATS)) {
            $key[CountryContext::class] = $this->countryContext->getActiveId();
        }

        return $key;
    }

    protected function getKeyFullPage(): ?array
    {
        if (findModule(\Modules::PROXY_CACHE)) {
            return $this->getKeyProxyFullPage();
        }

        return [];
    }

    protected function getKeyProxyFullPage(): ?array
    {
        return array_merge($this->getKeyText(), $this->getKeyPrice(), $this->getUserPriceLevelKey(), $this->getJsShopSectionKey());
    }

    protected function getUserPriceLevelKey()
    {
        if (!findModule(\Modules::PRICE_LEVELS)) {
            return [];
        }

        return [PriceLevelContext::class => Contexts::get(PriceLevelContext::class)->getActiveId()];
    }

    protected function getJsShopSectionKey()
    {
        if (!findModule(\Modules::COMPONENTS)) {
            return [];
        }

        return [JsShopSectionContext::class => Contexts::get(JsShopSectionContext::class)->getEncodedActiveId()];
    }

    public function getDefaultKey($types): ?string
    {
        return $this->contextManager->activateContexts($this->getDefaultKeyContexts(), function () use ($types) {
            return $this->getKey($types);
        });
    }

    protected function getDefaultKeyContexts(): array
    {
        $key = [
            CountryContext::class => $this->countryContext->getDefaultId(),
            UserContext::class => ContextManager::FORCE_EMPTY,
        ];

        if (findModule(\Modules::PRICE_LEVELS)) {
            $key[PriceLevelContext::class] = ContextManager::FORCE_EMPTY;
        }

        if (findModule(\Modules::COMPONENTS)) {
            $key[JsShopSectionContext::class] = ContextManager::FORCE_EMPTY;
        }

        if (findModule(\Modules::PRICELISTS)) {
            $key[PricelistContext::class] = Contexts::get(PricelistContext::class)->getDefaultId();
        }

        return $key;
    }
}
