<?php

declare(strict_types=1);

/**
 * @author Amasty Team
 * @copyright Copyright (c) Amasty (https://www.amasty.com)
 * @package Jet Theme Backend for Magento 2 (System)
 */

namespace Amasty\JetTheme\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\View\Design\ThemeInterface;
use Magento\Framework\View\DesignInterface;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Theme\Model\ResourceModel\Theme\Collection;
use Magento\Theme\Model\ResourceModel\Theme\CollectionFactory;
use Magento\Theme\Model\ThemeFactory;

class StoreThemeMapper
{
    public const THEME_FOLDER= 'Amasty/';

    /**
     * @var array
     */
    private $storeThemeMap = [];

    /**
     * @var StoreRepositoryInterface
     */
    private $storeRepository;

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

    /**
     * @var CollectionFactory
     */
    private $themeCollectionFactory;

    /**
     * @var DesignInterface
     */
    private $design;

    /**
     * @var ThemeFactory
     */
    private $themeFactory;

    public function __construct(
        StoreRepositoryInterface $storeRepository,
        ScopeConfigInterface $scopeConfig,
        CollectionFactory $themeCollectionFactory,
        DesignInterface $design,
        ThemeFactory $themeFactory
    ) {
        $this->storeRepository = $storeRepository;
        $this->scopeConfig = $scopeConfig;
        $this->themeCollectionFactory = $themeCollectionFactory;
        $this->design = $design;
        $this->themeFactory = $themeFactory;
    }

    /**
     * @param string $themeFilePath
     * @return int|null
     */
    public function getStoreIdByThemeFilePath(string $themeFilePath): ?int
    {
        $pathParts = explode('/', $themeFilePath);
        $themeName = $pathParts[0] . '/' . $pathParts[1];
        if (isset($this->storeThemeMap[$themeName])) {
            return $this->storeThemeMap[$themeName];
        }

        $theme = $this->themeCollectionFactory->create()
            ->addFieldToFilter('theme_path', $themeName)
            ->getFirstItem();

        $themeId = $theme->getThemeId();
        foreach ($this->storeRepository->getList() as $store) {
            $storeTheme = $this->scopeConfig->getValue(
                DesignInterface::XML_PATH_THEME_ID,
                ScopeInterface::SCOPE_STORE,
                $store->getId()
            );
            if ($storeTheme == $themeId) {
                $this->storeThemeMap[$themeName] = (int)$store->getId();
                return $this->storeThemeMap[$themeName];
            }
        }

        return null;
    }

    /**
     * @return Collection
     */
    public function getThemeCollection(): Collection
    {
        return $this->themeCollectionFactory->create();
    }

    /**
     * @return array
     */
    public function getStoresAppliedTheme(): array
    {
        $mainTheme = $this->themeCollectionFactory->create()
            ->addFieldToFilter('theme_path', 'Amasty/JetTheme')
            ->getFirstItem();
        $mainThemeId = $mainTheme->getThemeId();

        $themesIds = $this->themeCollectionFactory->create()
            ->addFieldToFilter('parent_id', $mainThemeId)
            ->getAllIds();
        $themesIds[] = $mainThemeId;
        $storesAppliedThemes = [];
        foreach ($this->storeRepository->getList() as $store) {
            $storeTheme = $this->scopeConfig->getValue(
                DesignInterface::XML_PATH_THEME_ID,
                ScopeInterface::SCOPE_STORE,
                $store->getId()
            );
            if (in_array($storeTheme, $themesIds)) {
                $storesAppliedThemes[] = $store->getName();
            }
        }

        return $storesAppliedThemes;
    }

    /**
     * @param int $themeId
     * @return bool
     */
    public function isThemeJetThemeById(int $themeId): bool
    {
        $theme = $this->themeFactory->create()->load($themeId);
        if (!$theme->getId()) {
            return false;
        }

        $themeCollection = $this->getThemeCollection();

        $themes = [];
        foreach ($themeCollection as $themeModel) {
            $themes[$themeModel->getId()] = $themeModel;
        }

        return $this->isParentThemeJetTheme($theme, $themes);
    }

    /**
     * @param ThemeInterface $theme
     * @param array $themes
     * @return bool
     */
    private function isParentThemeJetTheme(ThemeInterface $theme, array $themes): bool
    {
        if (strpos($theme->getThemePath(), "JetTheme") !== false) {
            return true;
        }

        if ($theme->getParentId()) {
            $this->isParentThemeJetTheme($themes[$theme->getParentId()], $themes);
        }

        return false;
    }

    /**
     * @return bool
     */
    public function isCurrentThemeJetTheme(): bool
    {
        $themePath = $this->design->getDesignTheme()->getThemePath();
        if ($themePath) {
            return strpos($this->design->getDesignTheme()->getThemePath(), self::THEME_FOLDER) !== false;
        }

        return false;
    }
}
