<?php

namespace KupShop\FeedGeneratorBundle\Feed;

use KupShop\FeedsBundle\Feed\BaseFeed;
use KupShop\FeedsBundle\FeedProductList;
use KupShop\FeedsBundle\Wrapper\ProductWrapper;
use Query\Operator;
use Query\QueryBuilder;

class ConfigurableFeed extends BaseFeed implements IConfigurableFeed
{
    use \DatabaseCommunication;
    use ConfigurableFeedTrait;

    /** @var string */
    public static $type = 'configurable';

    /** @var string */
    public static $alias = 'Varianty (výchozí)';

    public static function isAllowed(): bool
    {
        return (bool) findModule(\Modules::PRODUCTS);
    }

    public function __construct(ProductWrapper $productWrapper)
    {
        $this->objectWrapper = $productWrapper;
    }

    protected function fetchImages(\ProductList $productList): void
    {
        $productList->fetchImages(102, null, true);
        // additional images are fetched on demand
    }

    public function getProductList(int $feedID): FeedProductList
    {
        $productList = parent::getProductList($feedID);
        foreach ($this->specs as $spec) {
            $productList->andSpec($spec);
        }

        return $productList;
    }

    public function filterByObjectID($objectID): void
    {
        $this->specs[] = function (QueryBuilder $qb) use ($objectID) {
            $qb->andWhere('p.id=:product_id')->setParameter('product_id', $objectID);

            return '';
        };
    }

    public function getData(array $feedRow, ?int $limit = null): \Generator
    {
        $templateProductList = $this->productList ?? $this->getProductList($feedRow['id']);

        $queryProductIDs = $templateProductList->getQueryBuilder();
        $queryProductIDs->select('p.id AS id')
            ->groupBy('p.id');
        if (isset($limit)) {
            $queryProductIDs->setMaxResults($limit);
        }

        foreach (array_chunk($queryProductIDs->execute()->fetchFirstColumn(), static::$batchSize) as $ids) {
            $batchProductList = clone $templateProductList;
            $batchProductList->andSpec(function (QueryBuilder $qb) use ($ids) {
                $qb->andWhere(Operator::inIntArray($ids, 'p.id'));
            });

            // restrict the number of variations in configurator preview to 10 (configurator UI won't handle tens/hundreds of variations)
            if (isset($limit) && $limit === 1) {
                $batchProductList->limit(10);
            }

            $products = $batchProductList->getProducts();
            $this->objectWrapper->setProductCollection($products);
            foreach ($products as $product) {
                yield $this->prepareSingleObject($product);
            }
        }
    }
}
