<?php

declare(strict_types=1);

namespace KupShop\GraphQLBundle\ApiPublic\Util;

use KupShop\CatalogBundle\ProductList\ProductList;
use KupShop\GraphQLBundle\ApiAdmin\Types\Parameters;
use KupShop\GraphQLBundle\ApiPublic\Types\Collection\ProductPublicCollection;
use KupShop\GraphQLBundle\ApiPublic\Types\Product\ProductPublic;
use KupShop\GraphQLBundle\ApiShared\Types\Product\MultiSet\MultiSet;
use KupShop\GraphQLBundle\ApiShared\Util\ProductListUtil;
use KupShop\ProductSetsBundle\Utils\ProductCategories;
use KupShop\ShoppingListBundle\Util\ShoppingListUtil;
use Query\Operator;
use Query\QueryBuilder;

class ProductUtil
{
    public function __construct(
        private ProductList $productList,
        private ProductListUtil $productListUtil,
        private ?ProductCategories $productCategories = null,
        private ?ShoppingListUtil $shoppingListUtil = null,
    ) {
    }

    public function getProductMultiSet(int $productId, int $otherImagesSize): ?MultiSet
    {
        [$categories, $productCollection] = $this->productCategories->getCategoriesWithProductsResult($productId, false, true, $otherImagesSize);

        if (empty($categories)) {
            return null;
        }

        $setProduct = new \Product();
        $setProduct->createFromDB($productId);

        return new MultiSet(
            [
                'id' => $productId,
                'priceFrom' => $setProduct->getProductPrice(),
                'categories' => $categories,
                'inStore' => $setProduct->inStore ?? 0,
            ],
            $productCollection
        );
    }

    public function getProductFavorites(): array
    {
        if (findModule(\Modules::COMPONENTS)) {
            // favorites is special shopping list with label 'favorites'
            $favoritesList = $this->shoppingListUtil->getFavoritesShoppingList();
            if (!$favoritesList) {
                return [];
            }

            $listProducts = sqlQueryBuilder()->select('id_product')
                ->from('shopping_list_products')
                ->andWhere(Operator::equals(['id_shopping_list' => $favoritesList['id']]));
            $this->productList->andSpec(
                function (QueryBuilder $qb) use ($listProducts) {
                    $qb->joinSubQuery('p', $listProducts, 'pf', 'p.id = pf.id_product');
                });
            $this->productList->applyDefaultFilterParams();

            return $this->productList->getProducts()->getValues();
        }

        $filterParams = $this->productList->applyDefaultFilterParams();
        $filterParams->setCampaign('F');

        return $this->productList->getProducts()->getValues();
    }

    public function getProducts(?Parameters $filter): ProductPublicCollection
    {
        $filterValues = $filter ? array_filter($filter->getData()) : [];

        /** @var \ProductList $productList */
        $productList = clone $this->productList;

        // filters
        $specs = $this->productListUtil->getProductsFilterSpecs($filterValues);

        if (!empty($specs)) {
            $productList->andSpec(
                Operator::andX($specs)
            );
        }

        $totalCount = $productList->getProductsCount();

        $collection = $productList->getProducts();

        $products = [];
        foreach ($collection as $product) {
            $products[] = new ProductPublic($product, $collection);
        }

        return (new ProductPublicCollection($products))
            ->setItemsTotalCount($totalCount);
    }
}
