<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Remote\Entity\Provider;

use FiloBlu\Refilo\Helper\Catalog\CategoryHelper;
use FiloBlu\Refilo\Remote\Entity\CategoriesProduct;
use FiloBlu\Refilo\Remote\Entity\EntityProviderInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Select;
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\Data\WebsiteInterface;
use Magento\Store\Model\StoreManagerInterface;
use Zend_Db;

use function count;

/**
 * Class StockProvider
 * @package FiloBlu\Refilo\Remote\Entity\Provider
 */
class CategoriesProductProvider extends BaseProvider
{
    /** @var int */
    protected $website;

    /** @var ResourceConnection */
    private $resourceConnection;

    /** @var StoreManagerInterface */
    private $storeManager;
    /**
     * @var \FiloBlu\Refilo\Helper\Catalog\CategoryHelper
     */
    private $categoryHelper;

    /**
     * CategoriesProductProvider constructor.
     * @param ResourceConnection $resourceConnection
     * @param \FiloBlu\Refilo\Helper\Catalog\CategoryHelper $categoryHelper
     * @param StoreManagerInterface $storeManager
     * @param ScopeConfigInterface $scopeConfig
     */
    public function __construct(

        CategoryHelper $categoryHelper,
        ResourceConnection $resourceConnection,
        StoreManagerInterface $storeManager,
        ScopeConfigInterface $scopeConfig
    ) {
        parent::__construct($scopeConfig);
        $this->resourceConnection = $resourceConnection;
        $this->storeManager = $storeManager;
        $this->categoryHelper = $categoryHelper;
    }

    /**
     * @param array $item
     * @return \FiloBlu\Refilo\Remote\Entity\CategoriesProduct
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function createCategory(array $item) : CategoriesProduct
    {
        $data = [];
        $productId = (int)$item['product_id'];
        $data['id'] = $productId;
        $data['categories'] = [];

        foreach ($this->categoryHelper->getProductPositions($productId) as $categoryId => $position) {
            $data['category_' . $categoryId] = (int)$position;
            $data['categories'][] = $categoryId;

            foreach ($this->categoryHelper->getIsAnchorCategories($categoryId) as $parentId => $parentPosition) {
                $data['categories'][] = $parentId;
                $data['category_' . $parentId] = $this->categoryHelper->getProductPositionInsideCategory($productId, $parentId);
            }
        }

        if (count($data['categories']) > 0) {
            $categoriesWeight = $this->categoryHelper->getCategorySearchWeight($data['categories']);
            foreach ($categoriesWeight as $categoryWeight) {
                $data['category_weight_' . $categoryWeight['entity_id']] =
                    ($categoryWeight['value'] !== null && $categoryWeight['value'] !== '')
                        ? (int)$categoryWeight['value']
                        : 1;
            }
        }

        $data['categories'] = array_values(array_unique($data['categories']));

        return new CategoriesProduct($data);
    }

    /**
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    #[\ReturnTypeWillChange]
    public function rewind()
    {
        $select = $this->getSelectForProducts();

        $items = $this->resourceConnection->getConnection()->fetchAll($select, [], Zend_Db::FETCH_ASSOC);

        foreach ($items as $item) {
            $this->items[] = $this->createCategory($item);
        }

        if (!$this->hasReadHandler()) {
            return;
        }

        // TODO: Handle pagination
        $this->getReadHandler()->onRead($this->items, count($this->items), $this->getReadHandlerArguments());
    }

    /**
     * @return Select
     */
    protected function getSelectForProducts()
    {
        $select = $this->resourceConnection->getConnection()
            ->select()
            ->distinct(true)
            ->from(
                [
                    's' => 'catalog_category_product'
                ],
                [
                   'product_id' => 's.product_id',
                ]
            );

        if (!empty($this->ids)) {
            $select->where('s.product_id IN (?)', array_map('intval', $this->ids));
        }

        return $select;
    }

    /**
     * @param array $ids
     * @return EntityProviderInterface
     */
    public function withIds(array $ids): EntityProviderInterface
    {
        $this->ids = $ids;
        return $this;
    }

    /**
     * @param StoreInterface $store
     * @return EntityProviderInterface
     */
    public function forStore(StoreInterface $store): EntityProviderInterface
    {
        return $this;
    }

    /**
     * @param WebsiteInterface $website
     * @return EntityProviderInterface
     */
    public function forWebsite(WebsiteInterface $website): EntityProviderInterface
    {
        return $this;
    }

    /**
     * @return \Generator
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \Zend_Db_Statement_Exception
     */
    public function toGenerator(): \Generator
    {
        $select = $this->getSelectForProducts();
        $statement = $this->resourceConnection->getConnection()->query($select);

        while (($item = $statement->fetch(Zend_Db::FETCH_ASSOC))) {
            yield $this->createCategory($item);
        }
    }

    public function release(): EntityProviderInterface
    {
        $this->items = [];
        return $this;
    }
}
