<?php
/**
 * 2007-2023 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    PrestaShop SA <contact@prestashop.com>
 *  @copyright 2007-2023 PrestaShop SA
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */
declare(strict_types=1);

namespace PrestaShop\Module\AgileMultisellerPro\Repository;

use Doctrine\ORM\EntityRepository;
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
use PrestaShop\PrestaShop\Core\Product\ProductListingPresenter;

if (!defined('_PS_VERSION_')) {
    exit;
}

class SellerInfoProductRepository extends EntityRepository
{
    public function getProducts($sellerInfo, $p = 1, $n = 10, $orderby = '', $orderway = '', $extraConditions = '', $isTotal = false)
    {
        $context = \Context::getContext();

        $conn = $this->getEntityManager()->getConnection();

        $select = 'SELECT DISTINCT p.id_product AS idProduct';

        $from = ' FROM `' . _DB_PREFIX_ . 'product` p
            INNER JOIN `' . _DB_PREFIX_ . 'sellerinfo_product` sip ON (p.id_product=sip.id_product)
        ';

        $where = ' WHERE sip.id_sellerinfo = ' . (int) $sellerInfo->getIdSellerinfo();

        if ($extraConditions != '' || $orderby) {
            $select .= ', sav.quantity, IFNULL(product_shop.price, p.price) AS `default_price_amount`';
            $from .= 'INNER JOIN ' . _DB_PREFIX_ . 'product_shop product_shop ON (product_shop.id_product = p.id_product ' .
                'AND product_shop.id_shop = ' . \Configuration::get('PS_SHOP_DEFAULT') . ')
                    LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (pl.id_lang=' . (int) $context->language->id . ' AND ' .
                'p.`id_product` = pl.`id_product` ' . \Shop::addSqlRestrictionOnLang('pl') . ')
                    LEFT JOIN `' . _DB_PREFIX_ . 'tax_rule` tr ON ' .
                '(product_shop.`id_tax_rules_group` = tr.`id_tax_rules_group`
                      AND tr.`id_country` = ' . (int) $context->country->id . '
                      AND tr.`id_state` = 0)
                    LEFT JOIN `' . _DB_PREFIX_ . 'tax` t ON (t.`id_tax` = tr.`id_tax`)
                    LEFT JOIN `' . _DB_PREFIX_ . 'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`)
                    LEFT JOIN `' . _DB_PREFIX_ . 'supplier` s ON (s.`id_supplier` = p.`id_supplier`)
                LEFT JOIN `' . _DB_PREFIX_ . 'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1)
                LEFT JOIN `' . _DB_PREFIX_ .
                'stock_available` sav ON (sav.`id_product` = p.`id_product` AND sav.`id_product_attribute` = 0
                    AND sav.`id_shop` = ' . (int) $context->shop->id . ')
                LEFT JOIN `' . _DB_PREFIX_ .
                'category_lang` cl ON (p.id_category_default=cl.id_category AND cl.id_lang=' . (int) $context->language->id . ') ';
        }

        if ($extraConditions != '') {
            $where = $where . $extraConditions;
        }

        if (true === $isTotal) {
            return $conn->fetchColumn('SELECT COUNT(DISTINCT p.id_product)' . $from . $where);
        }

        if ($p < 1) {
            $p = 1;
        }

        if ($n < 1) {
            $n = 10;
        }

        if (empty($orderby)) {
            $orderby = 'p.date_add';
        }

        if (empty($orderway)) {
            $orderway = 'DESC';
        }

        $sort = ' ORDER BY ' . $orderby . ' ' . $orderway;

        $limit = ' LIMIT ' . (((int) $p - 1) * (int) $n) . ',' . (int) $n;

        $sql = $select . $from . $where . $sort . $limit;

        $products = $conn->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);

        return $this->prepareProducts($products);
    }

    public function getCountProducts($sellerInfo)
    {
        $conn = $this->getEntityManager()->getConnection();

        return (int) $conn->fetchColumn('
                SELECT COUNT(p.id_product) FROM ' . _DB_PREFIX_ . 'product AS p
                INNER JOIN `' . _DB_PREFIX_ . 'sellerinfo_product` sip ON (p.id_product=sip.id_product)
                WHERE sip.id_sellerinfo = ' . (int) $sellerInfo->getIdSellerinfo() . '
            ');
    }

    private function prepareProducts($products): array
    {
        $prepareProducts = [];

        if ($products && is_array($products)) {
            $context = \Context::getContext();
            $assembler = new \ProductAssembler($context);
            $presenterFactory = new \ProductPresenterFactory($context);
            $presentationSettings = $presenterFactory->getPresentationSettings();
            $presenter = new ProductListingPresenter(
                new ImageRetriever(
                    $context->link
                ),
                $context->link,
                new PriceFormatter(),
                new ProductColorsRetriever(),
                $context->getTranslator()
            );

            $defaultCurrency = \Currency::getDefaultCurrency();
            $priceFormatter = new PriceFormatter();

            foreach ($products as $product) {
                if (isset($product['idProduct'])) {
                    $product['id_product'] = (int) $product['idProduct'];
                }
                if (isset($product['default_price_amount'])) {
                    $product['default_price'] = $priceFormatter->format((float) $product['default_price_amount'], $defaultCurrency);
                }
                $assembledProduct = $assembler->assembleProduct($product);
                if (isset($product['quantity'])) {
                    // set product total quantity (summ of all combonations)
                    $assembledProduct['quantity'] = (int) $product['quantity'];
                }
                $prepareProducts[] = $presenter->present(
                    $presentationSettings,
                    $assembledProduct,
                    $context->language
                );
            }
        }

        return $prepareProducts;
    }
}
