<?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
 */

use PrestaShop\Module\AgileMultisellerPro\Controller\Front\AgileModuleFrontController;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoProduct;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\DataConfiguration;
use PrestaShop\Module\AgileMultisellerPro\Helper\AgileHelper;
use PrestaShop\PrestaShop\Core\Product\Search\Pagination;

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

class AgileMultiSellerProSellerProductsModuleFrontController extends AgileModuleFrontController
{
    private $sellerinfoProductRepository;

    public function init()
    {
        parent::init();

        $this->p = (int) Tools::getValue('page');

        if ($this->p <= 0) {
            $this->p = 1;
        }

        $this->n = (int) Tools::getValue('n');

        if ($this->n <= 0) {
            $this->n = max(1, (int) Configuration::get('PS_PRODUCTS_PER_PAGE'));
        }

        $this->orderBy = Tools::getValue('orderBy');

        if (!$this->orderBy) {
            $this->orderBy = 'p.date_add';
        }

        $this->orderWay = Tools::getValue('orderWay');

        if (!$this->orderWay) {
            $this->orderWay = 'DESC';
        }

        $action = Tools::getValue('process');
        $id_product = (int) Tools::getValue('id_product');

        if (isset($action) && isset($id_product)) {
            if ($action == 'delete' || $action == 'duplicate') {
                $targetIdSellerinfo = 0;
                $idSellerinfo = $this->sellerinfo->getIdSellerinfo();

                if ($sellerinfoProduct = $this->getSellerinfoProductRepository()
                    ->findOneBy(['sellerInfo' => $this->sellerinfo, 'idProduct' => $id_product])
                ) {
                    $targetIdSellerinfo = $sellerinfoProduct->getSellerinfo()->getIdSellerinfo();
                }

                if (
                    $idSellerinfo > 0
                    && $action == 'delete'
                    && $idSellerinfo == $targetIdSellerinfo
                ) {
                    $this->processDelete($sellerinfoProduct);
                } elseif (
                    $idSellerinfo > 0
                    && $action == 'duplicate'
                    && ($idSellerinfo == $targetIdSellerinfo || $targetIdSellerinfo == 0)
                ) {
                    $this->processDuplicate($id_product);
                } else {
                    $this->errors[] = $this->trans('You do not have permission to delete/duplicate this product or the product is not found.', [], 'Modules.Agilemultisellerpro.Products');
                }
            } elseif ($action == 'inactive' || $action == 'active') {
                $product = new Product((int) $id_product);
                $product->active = ($action == 'active');
                $product->update();
            }
        }

        if (isset($this->context->cookie->membership_product_limit_error)) {
            $this->errors[] = $this->context->cookie->membership_product_limit_error;
            $url = $this->context->link->getModuleLink($this->module->name, 'mymembership');
            $this->errors[] = implode('', ['<', 'a h', 'ref="', $url, '">', 'Make order', '</', 'a>']);
            unset($this->context->cookie->membership_product_limit_error);
        }
    }

    public function setMedia()
    {
        parent::setMedia();

        $this->addJqueryPlugin([
            'autocomplete',
        ]);

        $this->registerJavascript(
            'agile_sellerproducts',
            '/modules/agilemultisellerpro/views/js/front/sellerproducts.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile_sellerpage',
            '/modules/agilemultisellerpro/views/js/front/sellerpage.js',
            ['position' => 'bottom', 'priority' => 100]
        );
    }

    public function initContent()
    {
        parent::initContent();

        $products = $this->getSellerinfoProductRepository()
            ->getProducts($this->sellerinfo, $this->p, $this->n, $this->orderBy, $this->orderWay, $this->getExtraConditions());

        $numOfProducts = $this->getSellerinfoProductRepository()
                    ->getCountProducts($this->sellerinfo);

        $this->context->smarty->assign([
            'seller_tab_id' => 3,
            'numOfProducts' => $numOfProducts,
            'products' => $products,
            'pagination' => $this->getTemplateVarPagination(),
            'is_apprpved_required' => (int) Configuration::get('AGILE_MS_PRODUCT_APPROVAL'),
            'n' => $this->n,
            'p' => $this->p,
            'orderBy' => $this->orderBy,
            'orderWay' => $this->orderWay,
            'msgDelete' => $this->trans('Are you sure you want to delete selected product', [], 'Modules.Agilemultisellerpro.Products'),
            'msgDuplicate' => $this->trans('Are you sure you want to duplicate selected product', [], 'Modules.Agilemultisellerpro.Products'),
            'allowCopyMainStoreProduct' => (int) Configuration::get('AGILE_MS_PRODUCT_COPY'),
            'filter_id_product' => Tools::getValue('filter_id_product'),
            'filter_name' => Tools::getValue('filter_name'),
            'filter_category' => Tools::getValue('filter_category'),
            'filter_price' => Tools::getValue('filter_price'),
            'filter_quantity' => Tools::getValue('filter_quantity'),
            'filter_date_add_from' => Tools::getValue('filter_date_add_from'),
            'filter_date_add_to' => Tools::getValue('filter_date_add_to'),
            'filter_active' => Tools::getValue('filter_active'),
            'filter_approved' => Tools::getValue('filter_approved'),
        ]);

        $this->setTemplate('module:agilemultisellerpro/views/templates/front/sellerproducts.tpl');
    }

    private function getTemplateVarPagination()
    {
        $totalProductsCount = $this->getSellerinfoProductRepository()
            ->getProducts($this->sellerinfo, $this->p, $this->n, $this->orderBy, $this->orderWay, $this->getExtraConditions(), true);

        $page = $this->p;
        $perPage = $this->n;

        $pagination = new Pagination();
        $pagination
            ->setPage($page)
            ->setPagesCount(
                (int) ceil($totalProductsCount / $perPage)
            )
        ;

        $itemsShownFrom = ($perPage * ($page - 1)) + 1;
        $itemsShownTo = $perPage * $page;

        $pages = array_map(function ($link) {
            $link['url'] = $this->updateQueryString([
                'page' => $link['page'] > 1 ? $link['page'] : null,
            ]);

            return $link;
        }, $pagination->buildLinks());

        // Filter next/previous link on first/last page
        $pages = array_filter($pages, function ($page) use ($pagination) {
            if ('previous' === $page['type'] && 1 === $pagination->getPage()) {
                return false;
            }
            if ('next' === $page['type'] && $pagination->getPagesCount() === $pagination->getPage()) {
                return false;
            }

            return true;
        });

        return [
            'total_items' => $totalProductsCount,
            'items_shown_from' => $itemsShownFrom,
            'items_shown_to' => ($itemsShownTo <= $totalProductsCount) ? $itemsShownTo : $totalProductsCount,
            'current_page' => $pagination->getPage(),
            'pages_count' => $pagination->getPagesCount(),
            'pages' => $pages,
            // Compare to 3 because there are the next and previous links
            'should_be_displayed' => (count($pagination->buildLinks()) > 3),
        ];
    }

    private function getSellerinfoProductRepository()
    {
        if (empty($this->sellerinfoProductRepository)) {
            $this->sellerinfoProductRepository = $this->entityManager->getRepository(SellerinfoProduct::class);
        }

        return $this->sellerinfoProductRepository;
    }

    public function postProcess()
    {
        $export = Tools::getValue('export');
        if (!empty($export)) {
            header('Content-type: text/csv');
            header('Content-Type: application/force-download; charset=UTF-8');
            header('Cache-Control: no-store, no-cache');
            header('Content-disposition: attachment; filename="products_' . date('Y-m-d_His') . '.csv"');

            $products = $this->getSellerinfoProductRepository()
                ->getProducts($this->sellerinfo, $this->p, $this->n, $this->orderBy, $this->orderWay, $this->getExtraConditions());

            $data = $this->processExport($products);

            AgileHelper::hookGenerateCSV($data);
        }

        $bulkAction = Tools::getValue('bulkAction');
        $bulkActionData = explode(',', Tools::getValue('bulkActionData'));

        if (!empty($bulkAction) && !empty($bulkActionData)) {
            foreach ($bulkActionData as $id_product) {
                if ($id_product > 0) {
                    $targetIdSellerinfo = 0;
                    $idSellerinfo = $this->sellerinfo->getIdSellerinfo();

                    if ($sellerinfoProduct = $this->getSellerinfoProductRepository()
                        ->findOneBy(['sellerInfo' => $this->sellerinfo, 'idProduct' => $id_product])
                    ) {
                        $targetIdSellerinfo = $sellerinfoProduct->getSellerinfo()->getIdSellerinfo();
                    }

                    if (
                        $idSellerinfo > 0
                        && $bulkAction == 'delete'
                        && $idSellerinfo == $targetIdSellerinfo
                    ) {
                        $this->processDelete($sellerinfoProduct);
                    } elseif (
                        $idSellerinfo > 0
                        && ($bulkAction == 'enable' || $bulkAction == 'disable')
                        && $idSellerinfo == $targetIdSellerinfo
                    ) {
                        $product = new Product((int) $id_product);
                        $product->active = ($bulkAction == 'enable');
                        $product->update();
                    } else {
                        $this->errors[] = $this->trans('You do not have permission to delete/duplicate this ' .
                                'product or the product is not found.', [], 'Modules.Agilemultisellerpro.Products') . 'ID:' . $id_product;
                    }
                }
            }
        }
    }

    private function getExtraConditions()
    {
        $extraCondition = '';

        $filters = [
            ['name' => 'filter_id_product', 'type' => 'number'],
            ['name' => 'filter_name', 'type' => 'text'],
            ['name' => 'filter_category', 'type' => 'text'],
            ['name' => 'filter_quantity', 'type' => 'number'],
            ['name' => 'filter_price', 'type' => 'float'],
            ['name' => 'filter_active', 'type' => 'bool'],
            ['name' => 'filter_approved', 'type' => 'bool'],
            ['name' => 'filter_date_add', 'type' => 'date'],
        ];

        foreach ($filters as $filter) {
            $val = Tools::getValue($filter['name']);
            $len = Tools::strlen($val);

            switch ($filter['name']) {
                case 'filter_id_product':
                    if ((int) $val > 0) {
                        $extraCondition = $extraCondition . ' AND p.id_product = ' . (int) $val;
                    }

                    break;
                case 'filter_name':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . " AND pl.name LIKE '%" . pSQL($val) . "%'";
                    }

                    break;
                case 'filter_category':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . " AND cl.name LIKE '%" . pSQL($val) . "%'";
                    }

                    break;
                case 'filter_quantity':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . ' AND sav.quantity =' . (int) $val;
                    }

                    break;
                case 'filter_price':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . ' AND p.price =' . (float) $val;
                    }

                    break;
                case 'filter_active':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . ' AND p.active =' . (int) $val;
                    }

                    break;
                case 'filter_approved':
                    if ($len > 0) {
                        $extraCondition = $extraCondition . ' AND po.approved =' . (int) $val;
                    }

                    break;
                case 'filter_date_add':
                    $from = Tools::getValue($filter['name'] . '_from');
                    $to = Tools::getValue($filter['name'] . '_to');

                    if (!empty($from)) {
                        $extraCondition = $extraCondition . " AND p.date_add >='" . pSQL($from) . "'";
                    }

                    if (!empty($to)) {
                        $extraCondition = $extraCondition . " AND p.date_add <='" . pSQL($to) . "'";
                    }

                    break;
            }
        }

        return $extraCondition;
    }

    private function processDelete($sellerinfoProduct)
    {
        $product = new Product($sellerinfoProduct->getIdProduct());

        if (!$product->delete()) {
            $this->errors[] = $this->trans('Error occured during deleting the product.', [], 'Modules.Agilemultisellerpro.Products');
        }

        $this->entityManager->remove($sellerinfoProduct);
        $this->entityManager->flush();
    }

    private function processDuplicate($id_product)
    {
        if (Validate::isLoadedObject($product = new Product($id_product))) {
            $id_product_old = $product->id;

            if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) {
                $shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID());
                foreach ($shops as $shop) {
                    if ($product->isAssociatedToShop($shop['id_shop'])) {
                        $product_price = new Product($id_product_old, false, null, $shop['id_shop']);
                        $product->price = $product_price->price;
                    }
                }
            }

            unset($product->id);
            unset($product->id_product);
            $product->indexed = 0;
            $product->active = 0;

            if ($product->add()
                && Category::duplicateProductCategories($id_product_old, $product->id)
                && ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false
                && GroupReduction::duplicateReduction($id_product_old, $product->id)
                && Product::duplicateAccessories($id_product_old, $product->id)
                && Product::duplicateFeatures($id_product_old, $product->id)
                && Product::duplicateSpecificPrices($id_product_old, $product->id)
                && Pack::duplicate($id_product_old, $product->id)
                && Product::duplicateCustomizationFields($id_product_old, $product->id)
                && Product::duplicateTags($id_product_old, $product->id)
                && Product::duplicateDownload($id_product_old, $product->id)) {
                $sellerinfoProduct = new SellerinfoProduct();
                $sellerinfoProduct->setSellerinfo($this->sellerinfo)
                    ->setIdProduct($product->id)
                    ->setApproved((bool) !Configuration::get(DataConfiguration::AGILE_MS_PRODUCT_APPROVAL));

                $this->entityManager->persist($sellerinfoProduct);

                if ($this->entityManager->flush()) {
                    $this->errors[] = $this->trans('An error occurred while creating an object.', [], 'Modules.Agilemultisellerpro.Products');
                }

                if ($product->hasAttributes()) {
                    Product::updateDefaultAttribute($product->id);
                }

                if (!Tools::getValue('noimage') && !Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) {
                    $this->errors[] = $this->trans('An error occurred while copying images.', [], 'Modules.Agilemultisellerpro.Products');
                } else {
                    if (in_array($product->visibility, ['both', 'search']) && Configuration::get('PS_SEARCH_INDEXATION')) {
                        Search::indexation(false, $product->id);
                    }
                }
            } else {
                $this->errors[] = $this->trans('An error occurred while creating an object.', [], 'Modules.Agilemultisellerpro.Products');
            }
        }
    }

    public function processExport($list, $text_delimiter = '')
    {
        if (ob_get_level() && ob_get_length() > 0) {
            ob_clean();
        }

        $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));

        $fields = [
            'id_product' => $this->trans('ID', [], 'Modules.Agilemultisellerpro.Products'),
            'id_image' => $this->trans('Photo', [], 'Modules.Agilemultisellerpro.Products'),
            'name' => $this->trans('Name', [], 'Modules.Agilemultisellerpro.Products'),
            'category_name' => $this->trans('Category', [], 'Modules.Agilemultisellerpro.Products'),
            'currency' => $this->trans('Currency', [], 'Modules.Agilemultisellerpro.Products'),
            'price_amount' => $this->trans('Price', [], 'Modules.Agilemultisellerpro.Products'),
            'quantity' => $this->trans('Quantity', [], 'Modules.Agilemultisellerpro.Products'),
            'active' => $this->trans('Active', [], 'Modules.Agilemultisellerpro.Products'),
        ];

        $headers = [];

        foreach ($fields as $field => $header) {
            $headers[] = $header;
        }

        $content = [];

        foreach ($list as $i => $row) {
            $content[$i] = [];
            foreach ($fields as $field => $header) {
                switch ($field) {
                    case 'id_image':
                        if ($row['cover']) {
                            $content[$i][] = $row['cover']['small']['url'];
                        } else {
                            $content[$i][] = '';
                        }
                        break;
                    case 'active':
                        $content[$i][] = ($row[$field] == 1 ? 'Yes' : 'No');
                        break;
                    case 'currency':
                        $content[$i][] = $currency->name;
                        break;
                    default:
                        $content[$i][] = $row[$field];
                        break;
                }
            }
        }

        return [
            'export_precontent' => $this->trans('Date Range:', [], 'Modules.Agilemultisellerpro.Products')
                . Tools::getValue('date_from') . ' - ' . Tools::getValue('date_to'),
            'export_headers' => $headers,
            'export_content' => $content,
            'text_delimiter' => $text_delimiter,
        ];
    }
}
