<?php

declare(strict_types=1);

namespace KupShop\SalesBundle\SaleList;

use KupShop\CatalogBundle\ProductList\ProductList;
use KupShop\KupShopBundle\Util\Entity\EntityUtil;
use KupShop\SalesBundle\Entity\SaleItem;
use KupShop\SalesBundle\Util\SalesUtil;
use Query\Operator;
use Query\Product;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;

class MultiFetch
{
    public function __construct(
        protected readonly EntityUtil $entityUtil,
        protected readonly ProductList $productList,
    ) {
    }

    public function fetchItems(SaleCollection $sales): void
    {
        $this->fetchProductList($sales);

        $qb = sqlQueryBuilder()
            ->select('*')
            ->from('sales_items')
            ->where(Operator::inIntArray($sales->getSalesIds(), 'id_sale'));

        $result = [];
        foreach ($qb->execute() as $item) {
            $result[$item['id_sale']][$item['id']] = $this->entityUtil->createEntity(
                SalesUtil::prepareSaleItem($sales[$item['id_sale']], $item),
                SaleItem::class,
                new CamelCaseToSnakeCaseNameConverter()
            );
        }

        foreach ($sales as $sale) {
            $sale->items = $result[$sale->id] ?? [];
        }
    }

    public function fetchProductList(SaleCollection $sales): void
    {
        if ($sales->_productListFetched ?? false) {
            return;
        }

        $sales->_productListFetched = true;

        $productList = clone $this->productList;

        $productList->setVariationsAsResult(true);

        $qb = sqlQueryBuilder()
            ->select('id_sale, id_product, id_variation')
            ->from('sales_items')
            ->where(Operator::inIntArray($sales->getSalesIds(), 'id_sale'))
            ->andWhere('id_product IS NOT NULL');

        $products = [];
        $salesProducts = [];
        foreach ($qb->execute() as $item) {
            if (empty($item['id_product'])) {
                continue;
            }

            $products[$item['id_product']] = $products[$item['id_product']] ?? null;
            if ($item['id_variation']) {
                $products[$item['id_product']][] = $item['id_variation'];
            }

            $productListKey = $item['id_product'];
            if ($item['id_variation']) {
                $productListKey .= '/'.$item['id_variation'];
            }

            $salesProducts[$item['id_sale']][] = $productListKey;
        }

        // nemam co fetchovat
        if (empty($products)) {
            return;
        }

        $productList->andSpec(function () use ($products) {
            return Product::productsAndVariationsIds($products);
        });

        $products = $productList->getProducts();
        foreach ($sales as $sale) {
            foreach ($salesProducts[$sale->id] ?? [] as $key) {
                if ($products[$key] ?? false) {
                    $sale->productCollection->set($key, $products[$key]);
                }
            }
        }
    }
}
