<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Remote\Entity;

use FiloBlu\Refilo\Helper\Catalog\CategoryHelper;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory;

/**
 * Class MagentoToRefiloCategoryAdapter
 * @package FiloBlu\Refilo\Remote\Entity
 */
class MagentoToRefiloCategoryAdapter
{
    /**
     * @var array
     */
    protected $categoryUrlSuffix = [];

    /**
     * @var ScopeConfigInterface
     */
    private $scopeConfig;

    /**
     * @var CategoryHelper
     */
    private $categoryHelper;
    /**
     * @var UrlRewriteCollectionFactory
     */
    private $urlRewriteCollectionFactory;

    /**
     * MagentoToRefiloCategoryAdapter constructor.
     * @param CategoryHelper $categoryHelper
     * @param ScopeConfigInterface $scopeConfig
     * @param UrlRewriteCollectionFactory $urlRewriteCollectionFactory
     */
    public function __construct(
        CategoryHelper $categoryHelper,
        ScopeConfigInterface $scopeConfig,
        UrlRewriteCollectionFactory $urlRewriteCollectionFactory
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->categoryHelper = $categoryHelper;
        $this->urlRewriteCollectionFactory = $urlRewriteCollectionFactory;
    }

    /**
     * @param CategoryInterface|\Magento\Catalog\Model\Category $magentoCategory
     * @param Category $refiloCategory
     * @return Category
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function adapt(CategoryInterface $magentoCategory, Category $refiloCategory): Category
    {
        $image = ($magentoCategory->getData('image')) ? str_replace(
            '/media/',
            '',
            $magentoCategory->getData('image')
        ) : null;
        $mobileImage = ($magentoCategory->getData('mobile_image')) ? str_replace(
            '/media/',
            '',
            $magentoCategory->getData('mobile_image')
        ) : null;
        $attributes = $magentoCategory->getAttributes();
        // @TODO Every meta value is retrieved from Mageworx, please get rid of this module asap
        $refiloCategory
            ->setId($magentoCategory->getId())
            ->setEnabled($magentoCategory->getIsActive() ? '1' : '0')
            ->setParentId($magentoCategory->getParentId())
            ->setPosition($magentoCategory->getPosition())
            ->setCreatedAt($magentoCategory->getCreatedAt())
            ->setUpdatedAt($magentoCategory->getUpdatedAt())
            ->setPath($this->getUrlPath($magentoCategory))
            ->setPosition((int)$magentoCategory->getPosition())
            ->setLevel($magentoCategory->getLevel())
            ->setChildrenCount((int)$magentoCategory->getChildrenCount())
            ->setName($magentoCategory->getName())
            ->setDescription($this->categoryHelper->parseDescription($magentoCategory->getDescription()))
            ->setMetaTitle($magentoCategory->getMetaTitle())
            ->setMetaKeywords($magentoCategory->getMetaKeywords())
            ->setMetaDescription($magentoCategory->getMetaDescription())
            ->setMetaRobots($magentoCategory->getMetaRobots())
            ->setCategorySeoName($magentoCategory->getCategorySeoName())
            ->setIncludeInMenu($magentoCategory->getIncludeInMenu())
            ->setExcludeFromSearch((int)$magentoCategory->getRefiloExcludeFromSearch())
            ->setRefiloTemplate($magentoCategory->getRefiloTemplate())
            ->setFullName($this->categoryHelper->getFullName($magentoCategory))
            ->setIsAnchor((int)$magentoCategory->getIsAnchor())
            ->setImage($image)
            ->setMobileImage($mobileImage)
            ->setChildren($this->categoryHelper->getChildren($magentoCategory))
            ->setAllChildren($this->categoryHelper->getChildren($magentoCategory, true))
            ->setTileVariant($magentoCategory->getRefiloTileVariant())
            ->setHideFilters((bool)$magentoCategory->getRefiloHideFilters())
            ->setHideSortby((bool)$magentoCategory->getRefiloHideSortby())
            ->setHeadingVariant($magentoCategory->getRefiloHeadingVariant() ?? null)
            ->setCategoryIdentifier($magentoCategory->getRefiloCategoryIdentifier() ?? null)
            ->setRefiloViewModeEnabled((bool)$magentoCategory->getRefiloViewModeEnabled())
            ->setRefiloViewMode($magentoCategory->getRefiloViewMode() ?? null)
            ->setRefiloSiblingsCategoriesEnabled((bool)$magentoCategory->getRefiloSiblingsCategoriesEnabled())
            ->setRefiloChildrenCategoriesEnabled((bool)$magentoCategory->getRefiloChildrenCategoriesEnabled())
            ->setRefiloAncestorsCategoriesEnabled((bool)$magentoCategory->getRefiloAncestorsCategoriesEnabled())
            ->setEmotionalProducts($this->categoryHelper->getRefiloEmotionalProducts($magentoCategory))
            ->setRefiloSearchWeight((int)$magentoCategory->getRefiloSearchWeight());

        if (isset($attributes['refilo_search_weight'])
            && ($magentoCategory->getRefiloSearchWeight() === null || $magentoCategory->getRefiloSearchWeight() === 0)
        ) {
            $refiloCategory->setRefiloSearchWeight((int)$attributes['refilo_search_weight']->getDefaultValue());
        }

        if (isset($attributes['refilo_children_categories_enabled']) && $magentoCategory->getRefiloChildrenCategoriesEnabled() === null) {
            $refiloCategory->setRefiloChildrenCategoriesEnabled(
                (bool)$attributes['refilo_children_categories_enabled']->getDefaultValue()
            );
        }

        if (isset($attributes['refilo_siblings_categories_enabled']) && $magentoCategory->getRefiloSiblingsCategoriesEnabled() === null) {
            $refiloCategory->setRefiloSiblingsCategoriesEnabled(
            (bool)$attributes['refilo_siblings_categories_enabled']->getDefaultValue()
            );
        }

        if (isset($attributes['refilo_ancestors_categories_enabled']) && $magentoCategory->getRefiloAncestorsCategoriesEnabled() === null) {
            $refiloCategory->setRefiloAncestorsCategoriesEnabled(
                (bool)$attributes['refilo_ancestors_categories_enabled']->getDefaultValue()
            );
        }

        if (!$this->scopeConfig->isSetFlag('catalog/magento_catalogpermissions/enabled')) {
            $refiloCategory->setPermissions([]);
        }

        return $refiloCategory;
    }

    /**
     * Get public URL path for the given category.
     *
     * Tries the category model's `request_path` first. If not present, it loads URL rewrites
     * for the category and store and returns the first non-redirect `request_path`.
     * The returned path is always prefixed with a leading slash. Returns `null` when no
     * path is available or the category has no ID.
     *
     * @param CategoryInterface $category
     * @return string|null
     */
    public function getUrlPath(CategoryInterface $category): ?string
    {
        $storeId = $category->getStoreId();
        $categoryId = (int)$category->getId();

        if (!$categoryId) {
            return null;
        }

        // load category URL suffix for the store if not already loaded
        if (!isset($this->categoryUrlSuffix[$storeId])) {
            $this->categoryUrlSuffix[$storeId] = $this->scopeConfig->getValue(
                CategoryUrlPathGenerator::XML_PATH_CATEGORY_URL_SUFFIX,
                ScopeInterface::SCOPE_STORE,
                $storeId
            );
        }

        // use request_path if already present in the model
        $requestPath = $category->getData(UrlRewrite::REQUEST_PATH);
        if ($requestPath) {
            return '/' . ltrim($requestPath, '/'); //. $this->categoryUrlSuffix[$storeId];
        }

        // Load URL rewrites from DB for this category and store
        // Order by is_autogenerated DESC is added just for safety reasons, because the $category->getData(UrlRewrite::REQUEST_PATH) already should return the correct one
        $collection = $this->urlRewriteCollectionFactory->create()
            ->addFieldToFilter('entity_type', 'category')
            ->addFieldToFilter('entity_id', $categoryId)
            ->addFieldToFilter('store_id', $storeId)
            ->addFieldToFilter('redirect_type', 0)
            ->setOrder('is_autogenerated', 'DESC') // autogenerated first
            ->setPageSize(1);

        $urlRewrite = $collection->getFirstItem();

        if ($urlRewrite && $urlRewrite->getId()) {
            return '/' . ltrim($urlRewrite->getRequestPath(), '/');
        }

        // canonical path as last resort
        return "/catalog/category/view/id/$categoryId";
    }

}
