<?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 PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use PrestaShop\Module\AgileMultisellerPro\Controller\Front\AgileModuleFrontController;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoCategory;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoMembershipCustomer;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoMembershipType;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoProduct;
use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\DataConfiguration;

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

class AgileMultiSellerProProductImportModuleFrontController extends AgileModuleFrontController
{
    public static $column_mask;

    public $entities = [];

    public $available_fields = [];

    /** @var array|string[] */
    public $required_fields = [];

    public static $default_values = [];

    public static $validators = [
        'active' => ['AgileMultiSellerProProductImportModuleFrontController', 'getBoolean'],
        'tax_rate' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        /* Tax excluded */
        'price_tex' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        /* Tax included */
        'price_tin' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        'reduction_price' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        'reduction_percent' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        'wholesale_price' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        'ecotax' => ['AgileMultiSellerProProductImportModuleFrontController', 'getPrice'],
        'name' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'description' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'description_short' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'meta_title' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'meta_keywords' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'meta_description' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'link_rewrite' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'available_now' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'available_later' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'category' => ['AgileMultiSellerProProductImportModuleFrontController', 'split'],
        'online_only' => ['AgileMultiSellerProProductImportModuleFrontController', 'getBoolean'],
        'accessories' => ['AgileMultiSellerProProductImportModuleFrontController', 'split'],
        'image_alt' => ['AgileMultiSellerProProductImportModuleFrontController', 'split'],
        'delivery_in_stock' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
        'delivery_out_stock' => ['AgileMultiSellerProProductImportModuleFrontController', 'createMultiLangField'],
    ];

    public $separator;
    public $convert;
    public $display;
    public $multiple_value_separator;

    protected $importExecuted = false;

    protected $isNewCategory = false;
    protected $isProductLimit = true;
    protected $sellerinfoMembershipType = false;

    public function __construct()
    {
        $this->bootstrap = true;

        parent::__construct();

        @ini_set('max_execution_time', '0');
        define('MAX_LINE_SIZE', 0);
        define('UNFRIENDLY_ERROR', false);
        define('MAX_COLUMNS', 6);
        @ini_set('auto_detect_line_endings', '1');

        $this->entities = [
            $this->trans('Products', [], 'Admin.Global'),
        ];

        // @since 1.5.0
        if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
            $this->entities = array_merge(
                $this->entities,
                [
                    $this->trans('Supply Orders', [], 'Admin.Advparameters.Feature'),
                    $this->trans('Supply Order Details', [], 'Admin.Advparameters.Feature'),
                ]
            );
        }

        $this->entities = array_flip($this->entities);

        switch ((int) Tools::getValue('entity')) {
            case $this->entities[$this->trans('Products', [], 'Admin.Global')]:
                self::$validators['image'] = [
                    'AgileMultiSellerProProductImportModuleFrontController',
                    'split',
                ];

                $this->available_fields = [
                    'no' => ['label' => $this->trans('Ignore this column', [], 'Admin.Advparameters.Feature')],
                    'id' => ['label' => $this->trans('ID', [], 'Admin.Global')],
                    'active' => ['label' => $this->trans('Active (0/1)', [], 'Admin.Advparameters.Feature')],
                    'name' => ['label' => $this->trans('Name', [], 'Admin.Global') . '*'],
                    'category' => ['label' => $this->trans('Categories (x,y,z...)', [], 'Admin.Advparameters.Feature')],
                    'price_tex' => ['label' => $this->trans('Price tax excluded', [], 'Admin.Advparameters.Feature')],
                    'price_tin' => ['label' => $this->trans('Price tax included', [], 'Admin.Advparameters.Feature')],
                    'id_tax_rules_group' => ['label' => $this->trans('Tax rule ID', [], 'Admin.Advparameters.Feature')],
                    'wholesale_price' => ['label' => $this->trans('Cost price', [], 'Admin.Catalog.Feature')],
                    'on_sale' => ['label' => $this->trans('On sale (0/1)', [], 'Admin.Advparameters.Feature')],
                    'reduction_price' => ['label' => $this->trans('Discount amount', [], 'Admin.Advparameters.Feature')],
                    'reduction_percent' => ['label' => $this->trans('Discount percent', [], 'Admin.Advparameters.Feature')],
                    'reduction_from' => ['label' => $this->trans('Discount from (yyyy-mm-dd)', [], 'Admin.Advparameters.Feature')],
                    'reduction_to' => ['label' => $this->trans('Discount to (yyyy-mm-dd)', [], 'Admin.Advparameters.Feature')],
                    'reference' => ['label' => $this->trans('Reference #', [], 'Admin.Advparameters.Feature')],
                    'supplier_reference' => ['label' => $this->trans('Supplier reference #', [], 'Admin.Advparameters.Feature')],
                    'supplier' => ['label' => $this->trans('Supplier', [], 'Admin.Global')],
                    'manufacturer' => ['label' => $this->trans('Brand', [], 'Admin.Global')],
                    'ean13' => ['label' => $this->trans('EAN13', [], 'Admin.Advparameters.Feature')],
                    'upc' => ['label' => $this->trans('UPC', [], 'Admin.Advparameters.Feature')],
                    'mpn' => ['label' => $this->trans('MPN', [], 'Admin.Catalog.Feature')],
                    'ecotax' => ['label' => $this->trans('Ecotax', [], 'Admin.Catalog.Feature')],
                    'width' => ['label' => $this->trans('Width', [], 'Admin.Global')],
                    'height' => ['label' => $this->trans('Height', [], 'Admin.Global')],
                    'depth' => ['label' => $this->trans('Depth', [], 'Admin.Global')],
                    'weight' => ['label' => $this->trans('Weight', [], 'Admin.Global')],
                    'delivery_in_stock' => [
                        'label' => $this->trans(
                            'Delivery time of in-stock products:',
                            [],
                            'Admin.Catalog.Feature'
                        ),
                    ],
                    'delivery_out_stock' => [
                        'label' => $this->trans(
                            'Delivery time of out-of-stock products with allowed orders:',
                            [],
                            'Admin.Advparameters.Feature'
                        ),
                    ],
                    'quantity' => ['label' => $this->trans('Quantity', [], 'Admin.Global')],
                    'minimal_quantity' => ['label' => $this->trans('Minimal quantity', [], 'Admin.Advparameters.Feature')],
                    'low_stock_threshold' => ['label' => $this->trans('Low stock level', [], 'Admin.Catalog.Feature')],
                    'low_stock_alert' => ['label' => $this->trans('Receive a low stock alert by email', [], 'Admin.Catalog.Feature')],
                    'visibility' => ['label' => $this->trans('Visibility', [], 'Admin.Catalog.Feature')],
                    'additional_shipping_cost' => ['label' => $this->trans('Additional shipping cost', [], 'Admin.Advparameters.Feature')],
                    'unity' => ['label' => $this->trans('Unit for the price per unit', [], 'Admin.Advparameters.Feature')],
                    'unit_price' => ['label' => $this->trans('Price per unit', [], 'Admin.Advparameters.Feature')],
                    'description_short' => ['label' => $this->trans('Summary', [], 'Admin.Catalog.Feature')],
                    'description' => ['label' => $this->trans('Description', [], 'Admin.Global')],
                    'tags' => ['label' => $this->trans('Tags (x,y,z...)', [], 'Admin.Advparameters.Feature')],
                    'meta_title' => ['label' => $this->trans('Meta title', [], 'Admin.Global')],
                    'meta_keywords' => ['label' => $this->trans('Meta keywords', [], 'Admin.Global')],
                    'meta_description' => ['label' => $this->trans('Meta description', [], 'Admin.Global')],
                    'link_rewrite' => ['label' => $this->trans('Rewritten URL', [], 'Admin.Advparameters.Feature')],
                    'available_now' => ['label' => $this->trans('Label when in stock', [], 'Admin.Catalog.Feature')],
                    'available_later' => ['label' => $this->trans('Label when backorder allowed', [], 'Admin.Advparameters.Feature')],
                    'available_for_order' => ['label' => $this->trans('Available for order (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'available_date' => ['label' => $this->trans('Product availability date', [], 'Admin.Advparameters.Feature')],
                    'date_add' => ['label' => $this->trans('Product creation date', [], 'Admin.Advparameters.Feature')],
                    'show_price' => ['label' => $this->trans('Show price (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'image' => ['label' => $this->trans('Image URLs (x,y,z...)', [], 'Admin.Advparameters.Feature')],
                    'image_alt' => ['label' => $this->trans('Image alt texts (x,y,z...)', [], 'Admin.Advparameters.Feature')],
                    'delete_existing_images' => [
                        'label' => $this->trans('Delete existing images (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature'),
                    ],
                    'features' => ['label' => $this->trans('Feature (Name:Value:Position:Customized)', [], 'Admin.Advparameters.Feature')],
                    'online_only' => ['label' => $this->trans('Available online only (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'condition' => ['label' => $this->trans('Condition', [], 'Admin.Catalog.Feature')],
                    'customizable' => ['label' => $this->trans('Customizable (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'uploadable_files' => ['label' => $this->trans('Uploadable files (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'text_fields' => ['label' => $this->trans('Text fields (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'out_of_stock' => ['label' => $this->trans('Action when out of stock', [], 'Admin.Advparameters.Feature')],
                    'is_virtual' => ['label' => $this->trans('Virtual product (0 = No, 1 = Yes)', [], 'Admin.Advparameters.Feature')],
                    'file_url' => ['label' => $this->trans('File URL', [], 'Admin.Advparameters.Feature')],
                    'nb_downloadable' => [
                        'label' => $this->trans('Number of allowed downloads', [], 'Admin.Catalog.Feature'),
                        'help' => $this->trans('Number of days this file can be accessed by customers. Set to zero for unlimited access.', [], 'Admin.Catalog.Help'),
                    ],
                    'date_expiration' => ['label' => $this->trans('Expiration date (yyyy-mm-dd)', [], 'Admin.Advparameters.Feature')],
                    'nb_days_accessible' => [
                        'label' => $this->trans('Number of days', [], 'Admin.Advparameters.Feature'),
                        'help' => $this->trans('Number of days this file can be accessed by customers. Set to zero for unlimited access.', [], 'Admin.Catalog.Help'),
                    ],
                    'shop' => [
                        'label' => $this->trans('ID / Name of shop', [], 'Admin.Advparameters.Feature'),
                        'help' => $this->trans('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.', [], 'Admin.Advparameters.Help'),
                    ],
                    'advanced_stock_management' => [
                        'label' => $this->trans('Advanced Stock Management', [], 'Admin.Advparameters.Feature'),
                        'help' => $this->trans('Enable Advanced Stock Management on product (0 = No, 1 = Yes).', [], 'Admin.Advparameters.Help'),
                    ],
                    'depends_on_stock' => [
                        'label' => $this->trans('Depends on stock', [], 'Admin.Advparameters.Feature'),
                        'help' => $this->trans('0 = Use quantity set in product, 1 = Use quantity from warehouse.', [], 'Admin.Advparameters.Help'),
                    ],
                    'warehouse' => [
                        'label' => $this->trans('Warehouse', [], 'Admin.Advparameters.Feature'),
                        'help' => $this->trans('ID of the warehouse to set as storage.', [], 'Admin.Advparameters.Help'),
                    ],
                    'accessories' => ['label' => $this->trans('Accessories (x,y,z...)', [], 'Admin.Advparameters.Feature')],
                ];

                $idCategory = [];

                if (Configuration::get(DataConfiguration::AGILE_MS_ALLOW_REGISTER_ATHOME)) {
                    $idCategory = [(int) Configuration::get('PS_HOME_CATEGORY')];
                }

                self::$default_values = [
                    'id_category' => $idCategory,
                    'id_category_default' => null,
                    'active' => '1',
                    'width' => 0.000000,
                    'height' => 0.000000,
                    'depth' => 0.000000,
                    'weight' => 0.000000,
                    'visibility' => 'both',
                    'additional_shipping_cost' => 0.00,
                    'unit_price' => 0,
                    'quantity' => 0,
                    'minimal_quantity' => 1,
                    'low_stock_threshold' => null,
                    'low_stock_alert' => false,
                    'price' => 0,
                    'id_tax_rules_group' => 0,
                    'description_short' => [(int) Configuration::get('PS_LANG_DEFAULT') => ''],
                    'link_rewrite' => [(int) Configuration::get('PS_LANG_DEFAULT') => ''],
                    'online_only' => 0,
                    'condition' => 'new',
                    'available_date' => date('Y-m-d'),
                    'date_add' => date('Y-m-d H:i:s'),
                    'date_upd' => date('Y-m-d H:i:s'),
                    'customizable' => 0,
                    'uploadable_files' => 0,
                    'text_fields' => 0,
                    'advanced_stock_management' => 0,
                    'depends_on_stock' => 0,
                    'is_virtual' => 0,
                ];

                break;
        }

        $separator = Tools::substr((string) trim(Tools::getValue('separator')), 0, 1);
        $this->separator = $separator ? $separator : ';';
        $this->convert = false;
        $separator = Tools::substr((string) trim(Tools::getValue('multiple_value_separator')), 0, 1);
        $this->multiple_value_separator = $separator ? $separator : ',';
    }

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

        $this->registerJavascript(
            'agile-iframe-transport',
            '/modules/agilemultisellerpro/views/js/plugins/jquery.iframe-transport.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile-fileupload',
            '/modules/agilemultisellerpro/views/js/plugins/jquery.fileupload.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile-fileupload-process',
            '/modules/agilemultisellerpro/views/js/plugins/jquery.fileupload-process.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile-fileupload-validate',
            '/modules/agilemultisellerpro/views/js/plugins/jquery.fileupload-validate.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'js-vendor-spin',
            '/js/vendor/spin.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'js-vendor-ladda',
            '/js/vendor/ladda.js',
            ['position' => 'bottom', 'priority' => 100]
        );

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

        if ($this->display == 'import' && Tools::getValue('csv')) {
            $this->registerJavascript(
                'agile-productimportview-js',
                '/modules/agilemultisellerpro/views/js/front/import/productimportview.js',
                ['position' => 'bottom', 'priority' => 100]
            );
        } else {
            $this->registerJavascript(
                'agile-productimportform-js',
                '/modules/agilemultisellerpro/views/js/front/import/productimportform.js',
                ['position' => 'bottom', 'priority' => 100]
            );
        }
    }

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

        if (Tools::isSubmit('submitImportFile')) {
            $this->display = 'import';
        }
    }

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

        if ($this->display == 'import') {
            if (Tools::getValue('csv')) {
                $this->initImportView();
            } else {
                $this->errors[] = $this->trans('To proceed, please upload a file first.', [], 'Modules.Agilemultisellerpro.Import');
                $this->initImportForm();
            }
        } else {
            $this->initImportForm();
        }

        $this->context->smarty->assign([
            'seller_tab_id' => 11,
            'import_done' => $this->importExecuted ? 1 : 0,
        ]);
    }

    public function initImportForm()
    {
        if (!is_dir($this->getPath())) {
            return !($this->errors[] = $this->trans('The import directory doesn\'t exist. Please check your file path.', [], 'Modules.Agilemultisellerpro.Import'));
        }

        if (!is_writable($this->getPath())) {
            $this->displayWarning($this->trans('The import directory must be writable (CHMOD 755 / 777).', [], 'Modules.Agilemultisellerpro.Import'));
        }

        $files_to_import = scandir($this->getPath(), SCANDIR_SORT_NONE);
        uasort($files_to_import, ['AgileMultiSellerProProductImportModuleFrontController', 'usortFiles']);

        foreach ($files_to_import as $k => &$filename) {
            // exclude .  ..  .svn and index.php and all hidden files
            if (preg_match('/^\..*|index\.php/i', $filename) || is_dir($this->getPath() . $filename)) {
                unset($files_to_import[$k]);
            }
        }

        unset($filename);

        $this->fields_form = [''];

        $this->toolbar_scroll = false;
        $this->toolbar_btn = [];

        // adds fancybox
        $this->addJqueryPlugin(['fancybox']);

        $entity_selected = 0;
        if (isset($this->entities[$this->trans(Tools::ucfirst(Tools::getValue('import_type')))])) {
            $entity_selected = $this->entities[$this->trans(Tools::ucfirst(Tools::getValue('import_type')))];
            $this->context->cookie->entity_selected = (int) $entity_selected;
        } elseif (isset($this->context->cookie->entity_selected)) {
            $entity_selected = (int) $this->context->cookie->entity_selected;
        }

        $csv_selected = '';
        if (isset($this->context->cookie->csv_selected)
            && @filemtime($this->getPath(urldecode($this->context->cookie->csv_selected)))
        ) {
            $csv_selected = urldecode($this->context->cookie->csv_selected);
        } else {
            $this->context->cookie->csv_selected = $csv_selected;
        }

        $id_lang_selected = '';
        if (isset($this->context->cookie->iso_lang_selected) && $this->context->cookie->iso_lang_selected) {
            $id_lang_selected = (int) Language::getIdByIso(urldecode($this->context->cookie->iso_lang_selected));
        }

        $separator_selected = $this->separator;
        if (isset($this->context->cookie->separator_selected) && $this->context->cookie->separator_selected) {
            $separator_selected = urldecode($this->context->cookie->separator_selected);
        }

        $multiple_value_separator_selected = $this->multiple_value_separator;
        if (isset($this->context->cookie->multiple_value_separator_selected) && $this->context->cookie->multiple_value_separator_selected) {
            $multiple_value_separator_selected = urldecode($this->context->cookie->multiple_value_separator_selected);
        }

        // get post max size
        $post_max_size = ini_get('post_max_size');
        $bytes = (int) trim($post_max_size);
        $last = strtolower($post_max_size[strlen($post_max_size) - 1]);

        switch ($last) {
            case 'g':
                $bytes *= 1024;
                // no break to fall-through
            case 'm':
                $bytes *= 1024;
                // no break to fall-through
            case 'k':
                $bytes *= 1024;
        }

        if ($bytes == '') {
            $bytes = 20971520;
        } // 20Mb

        $this->context->smarty->assign([
            'import_confirmation' => Tools::isSubmit('import') && (isset($this->warnings) && !count($this->warnings)),
            'post_max_size' => (int) $bytes,
            'module_confirmation' => Tools::isSubmit('import') && (isset($this->warnings) && !count($this->warnings)),
            'path_import' => $this->getPath(),
            'entities' => $this->entities,
            'entity_selected' => $entity_selected,
            'csv_selected' => $csv_selected,
            'separator_selected' => $separator_selected,
            'multiple_value_separator_selected' => $multiple_value_separator_selected,
            'files_to_import' => $files_to_import,
            'languages' => Language::getLanguages(false),
            'id_language' => ($id_lang_selected) ? $id_lang_selected : $this->context->language->id,
            'available_fields' => $this->getAvailableFields(),
            'truncateAuthorized' => Shop::isFeatureActive() || !Shop::isFeatureActive(),
            'PS_ADVANCED_STOCK_MANAGEMENT' => Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'),
        ]);

        Media::addJsDef([
            'AST_PRODUCT_IMPORT_ALLOW_DELETE' => 1,
            'AST_PRODUCT_IMPORT_ALLOW_FORCE_ID' => 1,
            'post_max_size' => (int) $bytes,
            'truncateAuthorized' => Shop::isFeatureActive() || !Shop::isFeatureActive(),
            'ajax_csv_url' => $this->context->link->getModuleLink(
                'agilemultisellerpro',
                'productimport',
                ['ajax' => 1, 'action' => 'getCsvFromUrl'],
                true
            ),
            'importtools_url' => $this->context->link->getModuleLink('agilemultisellerpro', 'productimport', [], true),
            'confirm_msg' => $this->trans('Are you sure that you would like to delete all data of your', [], 'Modules.Agilemultisellerpro.Import'),
            'nopermission_msg' => $this->trans('You do not have permission to delete this. When the MultiStore mode is enabled, only a SuperAdmin can delete all items before an import', [], 'Modules.Agilemultisellerpro.Import'),
            'multiple_value_separator_selected' => $multiple_value_separator_selected,
        ]);

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

    public function displayAjaxGetCsvFromUrl()
    {
        $fileName = date('YmdHis') . '-data_from_url.csv';
        $csvUrl = Tools::getValue('csv_url');
        $fileGetContents = Tools::file_get_contents($csvUrl);
        $file = fopen($this->getPath() . $fileName, 'w');
        fwrite($file, $fileGetContents);
        fclose($file);
        $this->context->cookie->csv_selected = $fileName;
        exit(json_encode($fileName));
    }

    public function displayAjaxUploadCsv()
    {
        $filename_prefix = date('YmdHis') . '-';

        if (isset($_FILES['file']) && !empty($_FILES['file']['error'])) {
            switch ($_FILES['file']['error']) {
                case UPLOAD_ERR_INI_SIZE:
                    $_FILES['file']['error'] = $this->trans('The uploaded file exceeds the upload_max_filesize directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess.', [], 'Admin.Advparameters.Notification');

                    break;
                case UPLOAD_ERR_FORM_SIZE:
                    $_FILES['file']['error'] = $this->trans('The uploaded file exceeds the post_max_size directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess, for example:', [], 'Admin.Advparameters.Notification')
                    . '<br/><a href="' . $this->context->link->getAdminLink('AdminMeta') . '" >
                    <code>php_value post_max_size 20M</code> ' .
                    $this->trans('(click to open "Generators" page)', [], 'Admin.Advparameters.Notification') . '</a>';

                    break;
                case UPLOAD_ERR_PARTIAL:
                    $_FILES['file']['error'] = $this->trans('The uploaded file was only partially uploaded.', [], 'Admin.Advparameters.Notification');

                    break;
                case UPLOAD_ERR_NO_FILE:
                    $_FILES['file']['error'] = $this->trans('No file was uploaded.', [], 'Admin.Advparameters.Notification');

                    break;
            }
        } elseif (!preg_match('#([^\.]*?)\.(csv|xls[xt]?|o[dt]s)$#is', $_FILES['file']['name'])) {
            $_FILES['file']['error'] = $this->trans('The extension of your file should be .csv.', [], 'Admin.Advparameters.Notification');
        } elseif (!@filemtime($_FILES['file']['tmp_name'])
            || !@move_uploaded_file($_FILES['file']['tmp_name'], $this->getPath() . $filename_prefix . str_replace("\0", '', $_FILES['file']['name']))
        ) {
            $_FILES['file']['error'] = $this->trans('An error occurred while uploading / copying the file.', [], 'Admin.Advparameters.Notification');
        } else {
            @chmod($this->getPath() . $filename_prefix . $_FILES['file']['name'], 0664);
            $_FILES['file']['filename'] = $filename_prefix . str_replace('\0', '', $_FILES['file']['name']);
        }

        exit(json_encode($_FILES));
    }

    public function initImportView()
    {
        $this->addJS(_PS_JS_DIR_ . 'admin/import.js');

        $handle = $this->openCsvFile();
        $nb_column = $this->getNbrColumn($handle, $this->separator);
        $nb_table = ceil($nb_column / MAX_COLUMNS);

        $res = [];
        foreach ($this->required_fields as $elem) {
            $res[] = '\'' . $elem . '\'';
        }

        $data = [];
        for ($i = 0; $i < $nb_table; ++$i) {
            $data[$i] = $this->generateContentTable($i, $nb_column, $handle, $this->separator);
        }

        $this->context->cookie->entity_selected = (int) Tools::getValue('entity');
        $this->context->cookie->iso_lang_selected = urlencode(Tools::getValue('iso_lang'));
        $this->context->cookie->separator_selected = urlencode($this->separator);
        $this->context->cookie->multiple_value_separator_selected = urlencode($this->multiple_value_separator);
        $this->context->cookie->csv_selected = urlencode(Tools::getValue('csv'));

        $this->context->smarty->assign([
            'import_matchs' => Db::getInstance()->executeS('SELECT im.* FROM ' . _DB_PREFIX_ . 'import_match im
                LEFT JOIN `' . _DB_PREFIX_ . 'sellerinfo_import_match` sim
                    ON (sim.`id_import_match` = im.`id_import_match`)
                WHERE sim.`id_sellerinfo` = ' . (int) $this->sellerinfo->getIdSellerinfo(), true, false),
            'fields_value' => [
                'csv' => Tools::getValue('csv'),
                'entity' => (int) Tools::getValue('entity'),
                'iso_lang' => Tools::getValue('iso_lang'),
                'truncate' => Tools::getValue('truncate'),
                'forceIDs' => Tools::getValue('forceIDs'),
                'regenerate' => Tools::getValue('regenerate'),
                'sendemail' => Tools::getValue('sendemail'),
                'match_ref' => Tools::getValue('match_ref'),
                'separator' => $this->separator,
                'multiple_value_separator' => $this->multiple_value_separator,
            ],
            'nb_table' => $nb_table,
            'nb_column' => $nb_column,
            'res' => implode(',', $res),
            'max_columns' => MAX_COLUMNS,
            'no_pre_select' => ['price_tin', 'feature'],
            'available_fields' => $this->available_fields,
            'data' => $data,
        ]);

        Media::addJsDef([
            'importurl' => $this->context->link->getModuleLink('agilemultisellerpro', 'productimport', [], true),
            'errorEmpty' => $this->trans('Please name your data matching configuration in order to save it.', [], 'Modules.Agilemultisellerpro.Import'),
            'importProducts' => $this->trans('Importing products, please wait!', [], 'Modules.Agilemultisellerpro.Import'),
            'importProductsSucess' => $this->trans('Products successfully imported!', [], 'Modules.Agilemultisellerpro.Import'),
            'importProductsError' => $this->trans('There were errors while importing', [], 'Modules.Agilemultisellerpro.Import'),
        ]);

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

    protected function generateContentTable($current_table, $nb_column, $handle, $glue)
    {
        $html = '<table id="table' . $current_table . '" style="display: none;" class="table table-bordered"><thead><tr>';
        // Header
        for ($i = 0; $i < $nb_column; ++$i) {
            if (MAX_COLUMNS * (int) $current_table <= $i && (int) $i < MAX_COLUMNS * ((int) $current_table + 1)) {
                $html .= '<th>
                            <select id="type_value[' . $i . ']"
                                name="type_value[' . $i . ']"
                                class="type_value chosen form-control">
                                ' . $this->getTypeValuesOptions($i) . '
                            </select>
                        </th>';
            }
        }
        $html .= '</tr></thead><tbody>';

        self::setLocale();
        for ($current_line = 0; $current_line < 10 && $line = fgetcsv($handle, MAX_LINE_SIZE, $glue); ++$current_line) {
            /* UTF-8 conversion */
            if ($this->convert) {
                $line = $this->utf8EncodeArray($line);
            }
            $html .= '<tr id="table_' . $current_table . '_line_' . $current_line . '">';
            foreach ($line as $nb_c => $column) {
                if ((MAX_COLUMNS * (int) $current_table <= $nb_c) && ((int) $nb_c < MAX_COLUMNS * ((int) $current_table + 1))) {
                    $html .= '<td>' . htmlentities(Tools::substr($column, 0, 200), ENT_QUOTES, 'UTF-8') . '</td>';
                }
            }
            $html .= '</tr>';
        }
        $html .= '</tbody></table>';
        self::rewindBomAware($handle);

        return $html;
    }

    protected static function rewindBomAware($handle)
    {
        // A rewind wrapper that skips BOM signature wrongly
        if (!is_resource($handle)) {
            return false;
        }
        rewind($handle);
        if (($bom = fread($handle, 3)) != "\xEF\xBB\xBF") {
            rewind($handle);
        }
    }

    protected static function getBoolean($field)
    {
        return (bool) $field;
    }

    protected static function getPrice($field)
    {
        return (float) str_replace(
            [',', '%'],
            ['.', ''],
            $field
        );
    }

    protected static function split($field)
    {
        if (empty($field)) {
            return [];
        }

        $separator = Tools::getValue('multiple_value_separator');
        if (null === $separator || trim($separator) == '') {
            $separator = ',';
        }

        $tab = '';
        $uniqid_path = false;

        // try data:// protocole. If failed, old school file on filesystem.
        if (($fd = @fopen('data://text/plain;base64,' . base64_encode($field), 'rb')) === false) {
            do {
                $uniqid_path = _PS_UPLOAD_DIR_ . uniqid();
            } while (file_exists($uniqid_path));
            file_put_contents($uniqid_path, $field);
            $fd = fopen($uniqid_path, 'rb');
        }

        if ($fd === false) {
            return [];
        }

        $tab = fgetcsv($fd, MAX_LINE_SIZE, $separator);
        fclose($fd);
        if ($uniqid_path !== false && file_exists($uniqid_path)) {
            @unlink($uniqid_path);
        }

        if (empty($tab) || (!is_array($tab))) {
            return [];
        }

        return $tab;
    }

    protected static function createMultiLangField($field)
    {
        $res = [];
        foreach (Language::getIDs(false) as $id_lang) {
            $res[$id_lang] = $field;
        }

        return $res;
    }

    protected function getTypeValuesOptions($nb_c)
    {
        $i = 0;
        $no_pre_select = ['price_tin', 'feature'];

        $options = '';
        foreach ($this->available_fields as $k => $field) {
            $options .= '<option value="' . $k . '"';
            if ($k === 'price_tin') {
                ++$nb_c;
            }
            if ($i === ($nb_c + 1) && (!in_array($k, $no_pre_select))) {
                $options .= ' selected="selected"';
            }
            $options .= '>' . $field['label'] . '</option>';
            ++$i;
        }

        return $options;
    }

    public function getAvailableFields($in_array = false)
    {
        $i = 0;
        $fields = [];
        $keys = array_keys($this->available_fields);
        array_shift($keys);
        foreach ($this->available_fields as $k => $field) {
            if ($k === 'no') {
                continue;
            }
            if ($k === 'price_tin') { // Special case for Product : either one or the other. Not both.
                $fields[$i - 1] = '<div>' . $this->available_fields[$keys[$i - 1]]['label'] . '<br/>&nbsp;&nbsp;<i>' . $this->trans('or', [], 'Admin.Advparameters.Help') . '</i>&nbsp;&nbsp; ' . $field['label'] . '</div>';
            } else {
                if (isset($field['help'])) {
                    $html = '&nbsp;<span class="help-box" data-toggle="popover" data-content="' . $field['help'] . '"></span>';
                } else {
                    $html = '';
                }
                $fields[] = '<div>' . $field['label'] . $html . '</div>';
            }
            ++$i;
        }
        if ($in_array) {
            return $fields;
        } else {
            return implode("\n\r", $fields);
        }
    }

    protected function receiveTab()
    {
        $type_value = Tools::getValue('type_value') ? Tools::getValue('type_value') : [];
        foreach ($type_value as $nb => $type) {
            if ($type != 'no') {
                self::$column_mask[$type] = $nb;
            }
        }
    }

    public static function getMaskedRow($row)
    {
        $res = [];
        if (is_array(self::$column_mask)) {
            foreach (self::$column_mask as $type => $nb) {
                $res[$type] = isset($row[$nb]) ? trim($row[$nb]) : null;
            }
        }

        return $res;
    }

    protected static function setDefaultValues(&$info)
    {
        foreach (self::$default_values as $k => $v) {
            if (!isset($info[$k]) || $info[$k] == '') {
                $info[$k] = $v;
            }
        }
    }

    protected static function setEntityDefaultValues(&$entity)
    {
        $members = get_object_vars($entity);
        foreach (self::$default_values as $k => $v) {
            if ((array_key_exists($k, $members) && $entity->$k === null) || !array_key_exists($k, $members)) {
                $entity->$k = $v;
            }
        }
    }

    protected static function fillInfo($infos, $key, &$entity)
    {
        $infos = trim($infos);
        if (isset(self::$validators[$key][1]) && self::$validators[$key][1] == 'createMultiLangField' && Tools::getValue('iso_lang')) {
            $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
            $tmp = call_user_func(self::$validators[$key], $infos);
            foreach ($tmp as $id_lang_tmp => $value) {
                if (empty($entity->{$key}[$id_lang_tmp]) || $id_lang_tmp == $id_lang) {
                    $entity->{$key}[$id_lang_tmp] = $value;
                }
            }
        } elseif (!empty($infos) || $infos == '0') { // ($infos == '0') => if you want to disable a product by using "0" in active because empty('0') return true
            $entity->{$key} = isset(self::$validators[$key]) ? call_user_func(self::$validators[$key], $infos) : $infos;
        }

        return true;
    }

    public static function arrayWalk(&$array, $funcname, &$user_data = false)
    {
        if (!is_callable($funcname)) {
            return false;
        }

        foreach ($array as $k => $row) {
            if (!call_user_func_array($funcname, [$row, $k, &$user_data])) {
                return false;
            }
        }

        return true;
    }

    protected static function copyImg($id_entity, $id_image = null, $url = '', $entity = 'products', $regenerate = true)
    {
        $tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
        $watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));

        switch ($entity) {
            default:
            case 'products':
                $image_obj = new Image($id_image);
                $path = $image_obj->getPathForCreation();

                break;
            case 'categories':
                $path = _PS_CAT_IMG_DIR_ . (int) $id_entity;

                break;
            case 'manufacturers':
                $path = _PS_MANU_IMG_DIR_ . (int) $id_entity;

                break;
            case 'suppliers':
                $path = _PS_SUPP_IMG_DIR_ . (int) $id_entity;

                break;
            case 'stores':
                $path = _PS_STORE_IMG_DIR_ . (int) $id_entity;

                break;
        }

        $url = urldecode(trim($url));
        $parced_url = parse_url($url);

        if (isset($parced_url['path'])) {
            $uri = ltrim($parced_url['path'], '/');
            $parts = explode('/', $uri);
            foreach ($parts as &$part) {
                $part = rawurlencode($part);
            }
            unset($part);
            $parced_url['path'] = '/' . implode('/', $parts);
        }

        if (isset($parced_url['query'])) {
            $query_parts = [];
            parse_str($parced_url['query'], $query_parts);
            $parced_url['query'] = http_build_query($query_parts);
        }

        $url = http_build_url('', $parced_url);

        $orig_tmpfile = $tmpfile;

        if (Tools::copy($url, $tmpfile)) {
            // Evaluate the memory required to resize the image: if it's too much, you can't resize it.
            if (!ImageManager::checkImageMemoryLimit($tmpfile)) {
                @unlink($tmpfile);

                return false;
            }

            $tgt_width = $tgt_height = 0;
            $src_width = $src_height = 0;
            $error = 0;
            ImageManager::resize($tmpfile, $path . '.jpg', null, null, 'jpg', false, $error, $tgt_width, $tgt_height, 5, $src_width, $src_height);
            $images_types = ImageType::getImagesTypes($entity, true);

            if ($regenerate) {
                $path_infos = [];
                $path_infos[] = [$tgt_width, $tgt_height, $path . '.jpg'];
                foreach ($images_types as $image_type) {
                    $tmpfile = self::get_best_path($image_type['width'], $image_type['height'], $path_infos);

                    if (ImageManager::resize(
                        $tmpfile,
                        $path . '-' . stripslashes($image_type['name']) . '.jpg',
                        $image_type['width'],
                        $image_type['height'],
                        'jpg',
                        false,
                        $error,
                        $tgt_width,
                        $tgt_height,
                        5,
                        $src_width,
                        $src_height
                    )) {
                        // the last image should not be added in the candidate list if it's bigger than the original image
                        if ($tgt_width <= $src_width && $tgt_height <= $src_height) {
                            $path_infos[] = [$tgt_width, $tgt_height, $path . '-' . stripslashes($image_type['name']) . '.jpg'];
                        }
                        if ($entity == 'products') {
                            if (is_file(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int) $id_entity . '.jpg')) {
                                unlink(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int) $id_entity . '.jpg');
                            }
                            if (is_file(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int) $id_entity . '_' . (int) Context::getContext()->shop->id . '.jpg')) {
                                unlink(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int) $id_entity . '_' . (int) Context::getContext()->shop->id . '.jpg');
                            }
                        }
                    }
                }

                Hook::exec('actionWatermark', ['id_image' => $id_image, 'id_product' => $id_entity]);
            }
        } else {
            @unlink($orig_tmpfile);

            return false;
        }
        unlink($orig_tmpfile);

        return true;
    }

    protected static function get_best_path($tgt_width, $tgt_height, $path_infos)
    {
        $path_infos = array_reverse($path_infos);
        $path = '';
        foreach ($path_infos as $path_info) {
            list($width, $height, $path) = $path_info;
            if ($width >= $tgt_width && $height >= $tgt_height) {
                return $path;
            }
        }

        return $path;
    }

    public function productImport($offset = false, $limit = false, &$crossStepsVariables = false, $validateOnly = false, $moreStep = 0)
    {
        if ($moreStep == 1) {
            return $this->productImportAccessories($offset, $limit, $crossStepsVariables);
        }
        $this->receiveTab();
        $handle = $this->openCsvFile($offset);
        if (!$handle) {
            return false;
        }

        $default_language_id = (int) Configuration::get('PS_LANG_DEFAULT');
        $id_lang = Language::getIdByIso(Tools::getValue('iso_lang'));
        if (!Validate::isUnsignedId($id_lang)) {
            $id_lang = $default_language_id;
        }
        self::setLocale();
        $shop_ids = Shop::getCompleteListOfShopsID();

        $force_ids = Tools::getValue('forceIDs');
        $match_ref = Tools::getValue('match_ref');
        $regenerate = Tools::getValue('regenerate');
        $shop_is_feature_active = Shop::isFeatureActive();
        if (!$validateOnly) {
            Module::setBatchMode(true);
        }

        $accessories = [];
        if ($crossStepsVariables !== false && array_key_exists('accessories', $crossStepsVariables)) {
            $accessories = $crossStepsVariables['accessories'];
        }

        $line_count = 0;
        for ($current_line = 0; ($line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator)) && (!$limit || $current_line < $limit); ++$current_line) {
            ++$line_count;
            if ($this->convert) {
                $line = $this->utf8EncodeArray($line);
            }

            $isEmpty = empty(array_filter($line, 'strlen'));

            if ($isEmpty) {
                $this->warnings[] = $this->trans('Empty line skipped', [], 'Admin.Advparameters.Notification');
                continue;
            }

            if (count($line) == 1 && $line[0] == null) {
                $this->warnings[] = $this->trans('There is an empty row in the file that won\'t be imported.', [], 'Admin.Advparameters.Notification');

                continue;
            }

            $info = self::getMaskedRow($line);

            $res = $this->productImportOne(
                $info,
                $default_language_id,
                $id_lang,
                $force_ids,
                $regenerate,
                $shop_is_feature_active,
                $shop_ids,
                $match_ref,
                $accessories, // by ref
                $validateOnly
            );

            if (false === $res) {
                $this->isProductLimit = false;

                $this->errors[] = $this->trans(
                    'The subscription plan limit has been reached! Please order a new plan or upgrade your current one!',
                    [],
                    'Modules.Agilemultisellerpro.Product'
                );

                return $line_count;
            }
        }
        $this->closeCsvFile($handle);
        if (!$validateOnly) {
            Module::processDeferedFuncCall();
            Module::processDeferedClearCache();
            Tag::updateTagCount();
        }

        if ($crossStepsVariables !== false) {
            $crossStepsVariables['accessories'] = $accessories;
        }

        return $line_count;
    }

    protected function productImportAccessories($offset, $limit, &$crossStepsVariables)
    {
        if ($crossStepsVariables === false || !array_key_exists('accessories', $crossStepsVariables)) {
            return 0;
        }

        $accessories = $crossStepsVariables['accessories'];

        if ($offset == 0) {
            Module::setBatchMode(true);
        }

        $line_count = 0;
        $i = 0;
        foreach ($accessories as $product_id => $links) {
            // skip elements until reaches offset
            if ($i < $offset) {
                ++$i;

                continue;
            }

            if (count($links) > 0) { // We delete and relink only if there is accessories to link...
                // Bulk jobs: for performances, we need to do a minimum amount of SQL queries. No product inflation.
                $unique_ids = Product::getExistingIdsFromIdsOrRefs($links);
                Db::getInstance()->delete('accessory', 'id_product_1 = ' . (int) $product_id);
                Product::changeAccessoriesForProduct($unique_ids, $product_id);
            }
            ++$line_count;

            // Empty value to reduce array weight (that goes through HTTP requests each time) but do not unset array entry!
            $accessories[$product_id] = 0; // In JSON, 0 is lighter than null or false

            // stop when limit reached
            if ($line_count >= $limit) {
                break;
            }
        }

        if ($line_count < $limit) { // last pass only
            Module::processDeferedFuncCall();
            Module::processDeferedClearCache();
        }

        $crossStepsVariables['accessories'] = $accessories;

        return $line_count;
    }

    protected function productImportOne($info, $default_language_id, $id_lang, $force_ids, $regenerate, $shop_is_feature_active, $shop_ids, $match_ref, &$accessories, $validateOnly = false)
    {
        if (!$force_ids) {
            unset($info['id']);
        }

        $isError = false;
        $id_product = null;
        // Use product reference as key
        if (!empty($info['id'])) {
            $id_product = (int) $info['id'];
        } elseif ($match_ref && isset($info['reference'])) {
            $idProductByRef = (int) Db::getInstance()->getValue('
                                    SELECT p.`id_product`
                                    FROM `' . _DB_PREFIX_ . 'product` p
                                    ' . Shop::addSqlAssociation('product', 'p') . '
                                    WHERE p.`reference` = "' . pSQL($info['reference']) . '"
                                ', false);
            if ($idProductByRef) {
                $id_product = $idProductByRef;
            }
        }

        $product = new Product($id_product);

        $sellerinfoProduct = null;

        $update_advanced_stock_management_value = false;
        if (isset($product->id) && $product->id && Product::existsInDatabase((int) $product->id, 'product')) {
            // Check seller product
            $sellerinfoProductRepository = $this->entityManager->getRepository(SellerinfoProduct::class);
            $sellerinfoProduct = $sellerinfoProductRepository->findOneBy([
                'sellerInfo' => $this->sellerinfo,
                'idProduct' => (int) $product->id,
            ]);

            if (!$sellerinfoProduct || !$sellerinfoProduct->getIdProduct()) {
                $this->errors[] = $this->trans(
                    'You do not have permission to import product with ID= %d',
                    [$product->id],
                    'Modules.Agilemultisellerpro.Import'
                );

                return;
            }

            $product->loadStockData();
            $update_advanced_stock_management_value = true;
            $category_data = Product::getProductCategories((int) $product->id);

            if (is_array($category_data)) {
                foreach ($category_data as $tmp) {
                    if ($product->category && is_array($product->category)) {
                        continue;
                    }
                    $product->category[] = $tmp;
                }
            }
        } elseif (false === $this->isProductLimitError()) {
            return false;
        }

        self::setEntityDefaultValues($product);
        self::arrayWalk($info, ['AgileMultiSellerProProductImportModuleFrontController', 'fillInfo'], $product);

        /** @var Product|null $product */
        if (!$product) {
            return;
        }

        if (!$shop_is_feature_active) {
            $product->shop = (int) Configuration::get('PS_SHOP_DEFAULT');
        } elseif (!isset($product->shop) || empty($product->shop)) {
            $product->shop = implode($this->multiple_value_separator, Shop::getContextListShopID());
        }

        if (!$shop_is_feature_active) {
            $product->id_shop_default = (int) Configuration::get('PS_SHOP_DEFAULT');
        } else {
            $product->id_shop_default = (int) Context::getContext()->shop->id;
        }

        // link product to shops
        foreach (explode($this->multiple_value_separator, $product->shop) as $shop) {
            if (!empty($shop) && !is_numeric($shop)) {
                $product->id_shop_list[] = Shop::getIdByName($shop);
            } elseif (!empty($shop)) {
                $product->id_shop_list[] = $shop;
            }
        }

        if ((int) $product->id_tax_rules_group != 0) {
            if (Validate::isLoadedObject(new TaxRulesGroup($product->id_tax_rules_group))) {
                $address = $this->context->shop->getAddress();
                $tax_manager = TaxManagerFactory::getManager($address, $product->id_tax_rules_group);
                $product_tax_calculator = $tax_manager->getTaxCalculator();
                $product->tax_rate = $product_tax_calculator->getTotalRate();
            } else {
                $this->addProductWarning(
                    'id_tax_rules_group',
                    $product->id_tax_rules_group,
                    $this->trans('Unknown tax rule group ID. You need to create a group with this ID first.', [], 'Admin.Advparameters.Notification')
                );
            }
        }
        if (isset($product->manufacturer) && is_numeric($product->manufacturer) && Manufacturer::manufacturerExists((int) $product->manufacturer)) {
            $product->id_manufacturer = (int) $product->manufacturer;
        } elseif (isset($product->manufacturer) && is_string($product->manufacturer) && !empty($product->manufacturer)) {
            if ($manufacturer = Manufacturer::getIdByName($product->manufacturer)) {
                $product->id_manufacturer = (int) $manufacturer;
            } else {
                $manufacturer = new Manufacturer();
                $manufacturer->name = $product->manufacturer;
                $manufacturer->active = true;
                if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true
                    && ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true
                    && !$validateOnly
                    // Do not move this condition: previous tests should be played always, but next ->add() test should not be played in validateOnly mode
                    && $manufacturer->add()
                ) {
                    $product->id_manufacturer = (int) $manufacturer->id;
                    $manufacturer->associateTo($product->id_shop_list);
                } else {
                    if (!$validateOnly) {
                        $this->errors[] = sprintf(
                            $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Admin.Advparameters.Notification'),
                            Tools::htmlentitiesUTF8($manufacturer->name),
                            !empty($manufacturer->id) ? $manufacturer->id : 'null'
                        );
                    }
                    if ($field_error !== true || isset($lang_field_error) && $lang_field_error !== true) {
                        $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') .
                            Db::getInstance()->getMsgError();
                    }
                }
            }
        }

        if (isset($product->supplier) && is_numeric($product->supplier) && Supplier::supplierExists((int) $product->supplier)) {
            $product->id_supplier = (int) $product->supplier;
        } elseif (isset($product->supplier) && is_string($product->supplier) && !empty($product->supplier)) {
            if ($supplier = Supplier::getIdByName($product->supplier)) {
                $product->id_supplier = (int) $supplier;
            } else {
                $supplier = new Supplier();
                $supplier->name = $product->supplier;
                $supplier->active = true;

                if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true
                    && ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true
                    && !$validateOnly
                    // Do not move this condition: previous tests should be played always, but next ->add() test should not be played in validateOnly mode
                    && $supplier->add()
                ) {
                    $product->id_supplier = (int) $supplier->id;
                    $supplier->associateTo($product->id_shop_list);
                } else {
                    if (!$validateOnly) {
                        $this->errors[] = sprintf(
                            $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Admin.Advparameters.Notification'),
                            Tools::htmlentitiesUTF8($supplier->name),
                            !empty($supplier->id) ? Tools::htmlentitiesUTF8($supplier->id) : 'null'
                        );
                    }
                    if ($field_error !== true || isset($lang_field_error) && $lang_field_error !== true) {
                        $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') .
                            Db::getInstance()->getMsgError();
                    }
                }
            }
        }

        if (isset($product->price_tex) && !isset($product->price_tin)) {
            $product->price = $product->price_tex;
        } elseif (isset($product->price_tin) && !isset($product->price_tex)) {
            $product->price = $product->price_tin;
            // If a tax is already included in price, withdraw it from price
            if ($product->tax_rate) {
                $product->price = (float) number_format($product->price / (1 + $product->tax_rate / 100), 6, '.', '');
            }
        } elseif (isset($product->price_tin, $product->price_tex)) {
            $product->price = $product->price_tex;
        }

        if (!Configuration::get('PS_USE_ECOTAX')) {
            $product->ecotax = 0;
        }

        $defCategory = new Category(
            Configuration::get(DataConfiguration::AGILE_MS_DEFAULT_CATEGORY),
            $default_language_id
        );

        if (!empty($product->category) && is_array($product->category)) {
            $product->id_category = []; // Reset default values array

            $sellerIdsCategories = $this->entityManager
                ->getRepository(SellerinfoCategory::class)
                ->getSellerIdsCategories($this->sellerinfo->getIdSellerinfo());

            foreach ($product->category as $value) {
                $this->isNewCategory = false;
                if (is_numeric($value)) {
                    if (Category::categoryExists((int) $value)) {
                        if (in_array((int) $value, $sellerIdsCategories)) {
                            $product->id_category[] = (int) $value;
                        }
                    } elseif (Configuration::get(DataConfiguration::AGILE_MS_EDIT_CATEGORY)) {
                        $category_to_create = new Category();
                        $category_to_create->id = (int) $value;
                        $category_to_create->name = self::createMultiLangField($value);
                        $category_to_create->active = true;
                        $category_to_create->id_parent = (int) Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create
                        $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]);
                        $category_to_create->link_rewrite = self::createMultiLangField($category_link_rewrite);
                        if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true
                            && ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true
                            && !$validateOnly
                            // Do not move this condition: previous tests should be played always, but next ->add() test should not be played in validateOnly mode
                            && $category_to_create->add()
                        ) {
                            $product->id_category[] = (int) $category_to_create->id;
                            $this->addSellerInfoCategory($category_to_create->id);
                        } else {
                            if (!$validateOnly) {
                                $this->errors[] = sprintf(
                                    $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Admin.Advparameters.Notification'),
                                    Tools::htmlentitiesUTF8($category_to_create->name[$default_language_id]),
                                    !empty($category_to_create->id) ? Tools::htmlentitiesUTF8($category_to_create->id) : 'null'
                                );
                            }
                            if ($field_error !== true || isset($lang_field_error) && $lang_field_error !== true) {
                                $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') .
                                    Db::getInstance()->getMsgError();
                            }
                        }
                    }
                } elseif (!$validateOnly && is_string($value) && !empty($value)) {
                    $category = Category::searchByPath($default_language_id, trim($value), $this, 'productImportCreateCat');

                    if (
                        isset($category['id_category'])
                        && $category['id_category']
                        && (
                            in_array((int) $category['id_category'], $sellerIdsCategories)
                            || true === $this->isNewCategory
                        )
                    ) {
                        $product->id_category[] = (int) $category['id_category'];
                        $this->addSellerInfoCategory($category['id_category']);
                    } elseif (Validate::isLoadedObject($defCategory)) {
                        $product->id_category[] = (int) $defCategory->id;
                    } elseif (false === $this->isNewCategory) {
                        $isError = true;
                    }
                }
            }

            $product->id_category = array_values(array_unique($product->id_category));
        }

        // Category default now takes the value of the first new category during import
        if (isset($product->id_category[0])) {
            if (empty($product->id_category_default) || !in_array($product->id_category_default, $product->id_category)) {
                $product->id_category_default = (int) $product->id_category[0];
            }
        } else {
            if (empty($product->id_category_default)) {
                if (Validate::isLoadedObject($defCategory)) {
                    $product->id_category_default = $defCategory->id;
                } else {
                    $defaultProductShop = new Shop($product->id_shop_default);
                    $product->id_category_default = Category::getRootCategory(null, Validate::isLoadedObject($defaultProductShop) ? $defaultProductShop : null)->id;
                }
            }

            $product->id_category[] = $product->id_category_default;
        }

        $link_rewrite = (is_array($product->link_rewrite) && isset($product->link_rewrite[$id_lang])) ? trim($product->link_rewrite[$id_lang]) : '';
        $valid_link = Validate::isLinkRewrite($link_rewrite);
        if ((isset($product->link_rewrite[$id_lang]) && empty($product->link_rewrite[$id_lang])) || !$valid_link) {
            $link_rewrite = Tools::link_rewrite($product->name[$id_lang]);
            if ($link_rewrite == '') {
                $link_rewrite = 'friendly-url-autogeneration-failed';
            }
        }

        if (!$valid_link) {
            $this->informations[] = $this->trans(
                'Rewrite link for %1$s (ID %2$s): re-written as %3$s.',
                [
                    '%1$s' => Tools::htmlentitiesUTF8($product->name[$id_lang]),
                    '%2$s' => !empty($info['id']) ? Tools::htmlentitiesUTF8($info['id']) : 'null',
                    '%3$s' => Tools::htmlentitiesUTF8($link_rewrite),
                ],
                'Admin.Advparameters.Notification'
            );
        }

        if (!$valid_link || !(is_array($product->link_rewrite) && count($product->link_rewrite))) {
            $product->link_rewrite = self::createMultiLangField($link_rewrite);
        } else {
            $product->link_rewrite[(int) $id_lang] = $link_rewrite;
        }

        // replace the value of separator by coma
        if ($this->multiple_value_separator != ',') {
            if (is_array($product->meta_keywords)) {
                foreach ($product->meta_keywords as &$meta_keyword) {
                    if (!empty($meta_keyword)) {
                        $meta_keyword = str_replace($this->multiple_value_separator, ',', $meta_keyword);
                    }
                }
            }
        }

        // Convert comma into dot for all floating values
        foreach (Product::$definition['fields'] as $key => $array) {
            if ($array['type'] == Product::TYPE_FLOAT) {
                $product->{$key} = str_replace(',', '.', $product->{$key});
            }
        }

        // Indexation is already 0 if it's a new product, but not if it's an update
        $product->indexed = false;
        $productExistsInDatabase = false;

        if ($product->id && Product::existsInDatabase((int) $product->id, 'product')) {
            $productExistsInDatabase = true;
        }

        if (($match_ref && $product->reference && $product->existsRefInDatabase($product->reference)) || $productExistsInDatabase) {
            $product->date_upd = date('Y-m-d H:i:s');
        }

        $res = false;
        $field_error = $product->validateFields(UNFRIENDLY_ERROR, true);
        $lang_field_error = $product->validateFieldsLang(UNFRIENDLY_ERROR, true);
        if ($isError === false && $field_error === true && $lang_field_error === true) {
            // check quantity
            if ($product->quantity == null) {
                $product->quantity = 0;
            }

            // If match ref is specified && ref product && ref product already in base, trying to update
            if ($match_ref && $product->reference && $product->existsRefInDatabase($product->reference)) {
                $datas = Db::getInstance()->getRow('
                    SELECT product_shop.`date_add`, p.`id_product`
                    FROM `' . _DB_PREFIX_ . 'product` p
                    ' . Shop::addSqlAssociation('product', 'p') . '
                    WHERE p.`reference` = "' . pSQL($product->reference) . '"
                ', false);
                $product->id = (int) $datas['id_product'];
                $product->date_add = pSQL($datas['date_add']);
                $res = ($validateOnly || $product->update());
            } // Else If id product && id product already in base, trying to update
            elseif ($productExistsInDatabase) {
                $datas = Db::getInstance()->getRow('
                    SELECT product_shop.`date_add`
                    FROM `' . _DB_PREFIX_ . 'product` p
                    ' . Shop::addSqlAssociation('product', 'p') . '
                    WHERE p.`id_product` = ' . (int) $product->id, false);
                $product->date_add = pSQL($datas['date_add']);
                $res = ($validateOnly || $product->update());
            }
            // If no id_product or update failed
            $product->force_id = (bool) $force_ids;

            if (!$res) {
                if ($product->date_add != '') {
                    $res = ($validateOnly || $product->add(false));
                } else {
                    $res = ($validateOnly || $product->add());
                }
            }

            if (!$validateOnly) {
                if ($product->getType() == Product::PTYPE_VIRTUAL) {
                    StockAvailable::setProductOutOfStock((int) $product->id, 1);
                } else {
                    StockAvailable::setProductOutOfStock((int) $product->id, (int) $product->out_of_stock);
                }

                if ($product_download_id = ProductDownload::getIdFromIdProduct((int) $product->id)) {
                    $product_download = new ProductDownload($product_download_id);
                    $product_download->delete(true);
                }

                if ($product->getType() == Product::PTYPE_VIRTUAL) {
                    $product_download = new ProductDownload();
                    $product_download->filename = ProductDownload::getNewFilename();
                    Tools::copy($info['file_url'], _PS_DOWNLOAD_DIR_ . $product_download->filename);
                    $product_download->id_product = (int) $product->id;
                    $product_download->nb_downloadable = (int) $info['nb_downloadable'];
                    $product_download->date_expiration = $info['date_expiration'];
                    $product_download->nb_days_accessible = (int) $info['nb_days_accessible'];
                    $product_download->display_filename = basename($info['file_url']);
                    $product_download->add();
                }
            }
        }

        $shops = [];
        $product_shop = explode($this->multiple_value_separator, $product->shop);
        foreach ($product_shop as $shop) {
            if (empty($shop)) {
                continue;
            }
            $shop = trim($shop);
            if (!empty($shop) && !is_numeric($shop)) {
                $shop = Shop::getIdByName($shop);
            }

            if (in_array($shop, $shop_ids)) {
                $shops[] = $shop;
            } else {
                $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->trans('Shop is not valid', [], 'Admin.Advparameters.Notification'));
            }
        }
        if (empty($shops)) {
            $shops = Shop::getContextListShopID();
        }
        // If both failed, mysql error
        if (!$res) {
            $this->errors[] = sprintf(
                $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Admin.Advparameters.Notification'),
                !empty($info['name']) ? Tools::safeOutput($info['name']) : 'No Name',
                !empty($info['id']) ? Tools::safeOutput($info['id']) : 'No ID'
            );
            $this->errors[] = ($field_error !== true ? $field_error : '') . ($lang_field_error !== true ? $lang_field_error : '') .
                Db::getInstance()->getMsgError();
        } else {
            // Product supplier
            if (!$validateOnly && !empty($product->id) && property_exists($product, 'supplier_reference') && !empty($product->id_supplier)) {
                $id_product_supplier = (int) ProductSupplier::getIdByProductAndSupplier((int) $product->id, 0, (int) $product->id_supplier);
                if ($id_product_supplier) {
                    $product_supplier = new ProductSupplier($id_product_supplier);
                } else {
                    $product_supplier = new ProductSupplier();
                }
                $product_supplier->id_product = (int) $product->id;
                $product_supplier->id_product_attribute = 0;
                $product_supplier->id_supplier = (int) $product->id_supplier;
                $product_supplier->product_supplier_price_te = $product->wholesale_price;
                $product_supplier->product_supplier_reference = $product->supplier_reference;
                $product_supplier->id_currency = Currency::getDefaultCurrency()->id;
                $product_supplier->save();
            }

            // SpecificPrice (only the basic reduction feature is supported by the import)
            if (!$shop_is_feature_active) {
                $info['shop'] = 1;
            } elseif (!isset($info['shop']) || empty($info['shop'])) {
                $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID());
            }

            // Get shops for each attributes
            $info['shop'] = explode($this->multiple_value_separator, $info['shop']);

            $id_shop_list = [];
            foreach ($info['shop'] as $shop) {
                if (!empty($shop) && !is_numeric($shop)) {
                    $id_shop_list[] = (int) Shop::getIdByName($shop);
                } elseif (!empty($shop)) {
                    $id_shop_list[] = $shop;
                }
            }

            if ((isset($info['reduction_price']) && $info['reduction_price'] > 0) || (isset($info['reduction_percent']) && $info['reduction_percent'] > 0)) {
                foreach ($id_shop_list as $id_shop) {
                    $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, 0, 1, 0, 0, 0, 0);

                    if (is_array($specific_price) && isset($specific_price['id_specific_price'])) {
                        $specific_price = new SpecificPrice((int) $specific_price['id_specific_price']);
                    } else {
                        $specific_price = new SpecificPrice();
                    }
                    $specific_price->id_product = (int) $product->id;
                    $specific_price->id_specific_price_rule = 0;
                    $specific_price->id_shop = $id_shop;
                    $specific_price->id_currency = 0;
                    $specific_price->id_country = 0;
                    $specific_price->id_group = 0;
                    $specific_price->price = -1;
                    $specific_price->id_customer = 0;
                    $specific_price->from_quantity = 1;
                    $specific_price->reduction = (isset($info['reduction_price']) && $info['reduction_price']) ? (float) $info['reduction_price'] : (float) $info['reduction_percent'] / 100;
                    $specific_price->reduction_type = (isset($info['reduction_price']) && $info['reduction_price']) ? 'amount' : 'percentage';
                    $specific_price->from = (isset($info['reduction_from']) && Validate::isDate($info['reduction_from'])) ? $info['reduction_from'] : '0000-00-00 00:00:00';
                    $specific_price->to = (isset($info['reduction_to']) && Validate::isDate($info['reduction_to'])) ? $info['reduction_to'] : '0000-00-00 00:00:00';
                    if (!$validateOnly && !$specific_price->save()) {
                        $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->trans('Discount is invalid', [], 'Admin.Advparameters.Notification'));
                    }
                }
            }

            if (!$validateOnly && !empty($product->tags)) {
                if (isset($product->id) && $product->id) {
                    $tags = Tag::getProductTags($product->id);
                    if (is_array($tags) && count($tags)) {
                        /** @phpstan-ignore-next-line $product->tags is filled with a string at line 1986 */
                        $productTags = explode($this->multiple_value_separator, $product->tags);
                        foreach ($productTags as $key => $tag) {
                            if (!empty($tag)) {
                                $productTags[$key] = trim($tag);
                            }
                        }
                        $tags[$id_lang] = $productTags;
                        $product->tags = $tags;
                    }
                }
                // Delete tags for this id product, for no duplicating error
                Tag::deleteTagsForProduct($product->id);
                if (!is_array($product->tags) && !empty($product->tags)) {
                    $product->tags = self::createMultiLangField($product->tags);
                    foreach ($product->tags as $key => $tags) {
                        $is_tag_added = Tag::addTags($key, $product->id, $tags, $this->multiple_value_separator);
                        if (!$is_tag_added) {
                            $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->trans('Tags list is invalid', [], 'Admin.Advparameters.Notification'));

                            break;
                        }
                    }
                } else {
                    foreach ($product->tags as $key => $tags) {
                        $str = '';
                        foreach ($tags as $one_tag) {
                            $str .= $one_tag . $this->multiple_value_separator;
                        }
                        $str = rtrim($str, $this->multiple_value_separator);

                        $is_tag_added = Tag::addTags($key, $product->id, $str, $this->multiple_value_separator);
                        if (!$is_tag_added) {
                            $this->addProductWarning(Tools::safeOutput($info['name']), (int) $product->id, $this->trans(
                                'Invalid tag(s) (%s)',
                                [$str],
                                'Admin.Notifications.Error'
                            ));

                            break;
                        }
                    }
                }
            }

            // delete existing images if "delete_existing_images" is set to 1
            if (!$validateOnly && isset($product->delete_existing_images)) {
                if ((bool) $product->delete_existing_images) {
                    $product->deleteImages();
                }
            }

            if (!$validateOnly && isset($product->image) && is_array($product->image) && count($product->image)) {
                $product_has_images = (bool) Image::getImages($this->context->language->id, (int) $product->id);
                foreach ($product->image as $key => $url) {
                    $url = trim($url);
                    $error = false;
                    if (!empty($url)) {
                        $url = str_replace(' ', '%20', $url);

                        $image = new Image();
                        $image->id_product = (int) $product->id;
                        $image->position = Image::getHighestPosition($product->id) + 1;
                        $image->cover = (!$key && !$product_has_images) ? true : false;

                        $alt = '';
                        if (isset($product->image_alt[$key])) {
                            $alt = $product->image_alt[$key];
                        }

                        if (strlen($alt) > 0) {
                            $image->legend = self::createMultiLangField($alt);
                        }
                        // file_exists doesn't work with HTTP protocol
                        if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true
                            && ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true
                            && $image->add()
                        ) {
                            // associate image to selected shops
                            $image->associateTo($shops);
                            if (!self::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) {
                                $image->delete();
                                $this->warnings[] = $this->trans('Error copying image: %url%', ['%url%' => $url], 'Admin.Advparameters.Notification');
                            }
                        } else {
                            $error = true;
                        }
                    } else {
                        $error = true;
                    }

                    if ($error) {
                        $this->warnings[] = $this->trans(
                            'Product #%id%: the picture (%url%) cannot be saved.', [
                                '%id%' => Tools::htmlentitiesUTF8(isset($image) ? $image->id_product : ''),
                                '%url%' => Tools::htmlentitiesUTF8($url),
                            ],
                            'Admin.Advparameters.Notification'
                        );
                    }
                }
            }

            if (!$validateOnly && isset($product->id_category) && is_array($product->id_category)) {
                $product->updateCategories(array_map('intval', $product->id_category));
            }

            $product->checkDefaultAttributes();
            if (!$validateOnly && !$product->cache_default_attribute) {
                Product::updateDefaultAttribute($product->id);
            }

            // Features import
            $features = get_object_vars($product);

            if (!$validateOnly && isset($features['features']) && !empty($features['features'])) {
                foreach (explode($this->multiple_value_separator, $features['features']) as $single_feature) {
                    if (empty($single_feature)) {
                        continue;
                    }
                    $tab_feature = explode(':', $single_feature);
                    $feature_name = isset($tab_feature[0]) ? trim($tab_feature[0]) : '';
                    $feature_value = isset($tab_feature[1]) ? trim($tab_feature[1]) : '';
                    $position = isset($tab_feature[2]) ? (int) $tab_feature[2] - 1 : false;
                    $custom = isset($tab_feature[3]) ? (int) $tab_feature[3] : false;
                    if (!empty($feature_name) && !empty($feature_value)) {
                        $id_feature = (int) Feature::addFeatureImport($feature_name, $position);
                        $id_product = null;
                        if ($force_ids || $match_ref) {
                            $id_product = (int) $product->id;
                        }
                        $id_feature_value = (int) FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom);
                        Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value);
                    }
                }
            }
            // clean feature positions to avoid conflict
            Feature::cleanPositions();

            // set advanced stock managment
            if (!$validateOnly) {
                /* @phpstan-ignore-next-line Data from the property `advanced_stock_management` come from the database */
                if ($product->advanced_stock_management != 1 && $product->advanced_stock_management != 0) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management has incorrect value. Not set for product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management == 1) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, cannot enable on product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif ($update_advanced_stock_management_value) {
                    $product->setAdvancedStockManagement($product->advanced_stock_management);
                }
                // automaticly disable depends on stock, if a_s_m set to disabled
                if (StockAvailable::dependsOnStock($product->id) == 1 && $product->advanced_stock_management == 0) {
                    StockAvailable::setProductDependsOnStock($product->id, false);
                }
            }

            // Check if warehouse exists
            if (isset($product->warehouse) && $product->warehouse) {
                if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, warehouse not set on product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!$validateOnly) {
                    if (Warehouse::exists($product->warehouse)) {
                        // Get already associated warehouses
                        $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id);
                        // Delete any entry in warehouse for this product
                        foreach ($associated_warehouses_collection as $awc) {
                            $awc->delete();
                        }
                        $warehouse_location_entity = new WarehouseProductLocation();
                        $warehouse_location_entity->id_product = $product->id;
                        $warehouse_location_entity->id_product_attribute = 0;
                        $warehouse_location_entity->id_warehouse = $product->warehouse;
                        if (WarehouseProductLocation::getProductLocation($product->id, 0, $product->warehouse) !== false) {
                            $warehouse_location_entity->update();
                        } else {
                            $warehouse_location_entity->save();
                        }
                        StockAvailable::synchronize($product->id);
                    } else {
                        $this->warnings[] = $this->trans(
                            'Warehouse did not exist, cannot set on product %name%.',
                            [
                                '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                            ],
                            'Admin.Advparameters.Notification'
                        );
                    }
                }
            }

            // stock available
            if (isset($product->depends_on_stock)) {
                /* @phpstan-ignore-next-line Data from the property `depends_on_stock` come from the database */
                if ($product->depends_on_stock != 0 && $product->depends_on_stock != 1) {
                    $this->warnings[] = $this->trans(
                        'Incorrect value for "Depends on stock" for product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                /* @phpstan-ignore-next-line Data from properties `advanced_stock_management` & `depends_on_stock` come from the database */
                } elseif ((!$product->advanced_stock_management || $product->advanced_stock_management == 0) && $product->depends_on_stock == 1) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, cannot set "Depends on stock" for product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language_id]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!$validateOnly) {
                    StockAvailable::setProductDependsOnStock($product->id, $product->depends_on_stock);
                }

                // This code allows us to set qty and disable depends on stock
                if (!$validateOnly) {
                    // if depends on stock and quantity, add quantity to stock
                    if ($product->depends_on_stock == 1) {
                        $stock_manager = StockManagerFactory::getManager();
                        $price = str_replace(',', '.', (string) $product->wholesale_price);
                        if ($price == '0') {
                            $price = 0.000001;
                        }
                        $price = round((float) $price, 6);
                        $warehouse = new Warehouse($product->warehouse);
                        if ($stock_manager->addProduct((int) $product->id, 0, $warehouse, (int) $product->quantity, 1, $price, true)) {
                            StockAvailable::synchronize((int) $product->id);
                        }
                    } else {
                        if ($shop_is_feature_active) {
                            foreach ($shops as $shop) {
                                StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $shop);
                            }
                        } else {
                            StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $this->context->shop->id);
                        }
                    }
                }
            } elseif (!$validateOnly) {
                // if not depends_on_stock set, use normal qty
                if ($shop_is_feature_active) {
                    foreach ($shops as $shop) {
                        StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $shop);
                    }
                } else {
                    StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $this->context->shop->id);
                }
            }

            // Accessories linkage
            if (isset($product->accessories) && !$validateOnly && is_array($product->accessories) && count($product->accessories)) {
                $accessories[$product->id] = $product->accessories;
            }

            if (!$sellerinfoProduct || !$sellerinfoProduct->getIdProduct()) {
                // Add SellerinfoProduct
                $sellerinfoProduct = new SellerinfoProduct();
                $sellerinfoProduct
                    ->setSellerinfo($this->sellerinfo)
                    ->setIdProduct((int) $product->id)
                    ->setApproved(true);

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

    public function productImportCreateCat($default_language_id, $category_name, $id_parent_category = null)
    {
        if (!Configuration::get(DataConfiguration::AGILE_MS_EDIT_CATEGORY)) {
            $this->errors[] = $this->trans(
                '%data% cannot be saved - you are not allowed to create new categories!',
                [
                    '%data%' => Tools::htmlentitiesUTF8(trim($category_name)),
                ],
                'Admin.Advparameters.Notification'
            );

            return null;
        }

        $category_to_create = new Category();
        $shop_is_feature_active = Shop::isFeatureActive();
        if (!$shop_is_feature_active) {
            $category_to_create->id_shop_default = 1;
        } else {
            $category_to_create->id_shop_default = (int) Context::getContext()->shop->id;
        }
        $category_to_create->name = self::createMultiLangField(trim($category_name));
        $category_to_create->active = true;
        $category_to_create->id_parent = (int) $id_parent_category ? (int) $id_parent_category : (int) Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create
        $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]);
        $category_to_create->link_rewrite = self::createMultiLangField($category_link_rewrite);

        if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) !== true
            || ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) !== true
            || !$category_to_create->add()
        ) {
            $this->errors[] = sprintf(
                $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Admin.Advparameters.Notification'),
                Tools::htmlentitiesUTF8($category_to_create->name[$default_language_id]),
                !empty($category_to_create->id) ? Tools::htmlentitiesUTF8($category_to_create->id) : 'null'
            );
            if ($field_error !== true || isset($lang_field_error) && $lang_field_error !== true) {
                $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') .
                    Db::getInstance()->getMsgError();
            }
        }

        $this->isNewCategory = true;
    }

    public function attributeImport($offset = false, $limit = false, &$crossStepsVariables = false, $validateOnly = false)
    {
        $default_language = (int) Configuration::get('PS_LANG_DEFAULT');

        $groups = [];
        if ($crossStepsVariables !== false && array_key_exists('groups', $crossStepsVariables)) {
            $groups = $crossStepsVariables['groups'];
        }
        foreach (AttributeGroup::getAttributesGroups($default_language) as $group) {
            $groups[$group['name']] = (int) $group['id_attribute_group'];
        }

        $attributes = [];
        if ($crossStepsVariables !== false && array_key_exists('attributes', $crossStepsVariables)) {
            $attributes = $crossStepsVariables['attributes'];
        }
        foreach (ProductAttribute::getAttributes($default_language) as $attribute) {
            $attributes[$attribute['attribute_group'] . '_' . $attribute['name']] = (int) $attribute['id_attribute'];
        }

        $this->receiveTab();
        $handle = $this->openCsvFile($offset);
        if (!$handle) {
            return false;
        }

        self::setLocale();

        $regenerate = Tools::getValue('regenerate');
        $shop_is_feature_active = Shop::isFeatureActive();

        $line_count = 0;
        for ($current_line = 0; ($line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator)) && (!$limit || $current_line < $limit); ++$current_line) {
            ++$line_count;

            if ($this->convert) {
                $line = $this->utf8EncodeArray($line);
            }

            if (count($line) == 1 && $line[0] == null) {
                $this->warnings[] = $this->trans('There is an empty row in the file that won\'t be imported.', [], 'Admin.Advparameters.Notification');

                continue;
            }

            $info = self::getMaskedRow($line);
            $info = array_map('trim', $info);

            $this->attributeImportOne(
                $info,
                $default_language,
                $groups, // by ref
                $attributes, // by ref
                $regenerate,
                $shop_is_feature_active,
                $validateOnly
            );
        }
        $this->closeCsvFile($handle);

        if ($crossStepsVariables !== false) {
            $crossStepsVariables['groups'] = $groups;
            $crossStepsVariables['attributes'] = $attributes;
        }

        return $line_count;
    }

    protected function attributeImportOne($info, $default_language, &$groups, &$attributes, $regenerate, $shop_is_feature_active, $validateOnly = false)
    {
        self::setDefaultValues($info);

        if (!$shop_is_feature_active) {
            $info['shop'] = 1;
        } elseif (empty($info['shop'])) {
            $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID());
        }

        // Get shops for each attributes
        $info['shop'] = explode($this->multiple_value_separator, $info['shop']);

        $id_shop_list = [];
        if (is_array($info['shop'])) {
            foreach ($info['shop'] as $shop) {
                if (!empty($shop) && !is_numeric($shop)) {
                    $id_shop_list[] = Shop::getIdByName($shop);
                } elseif (!empty($shop)) {
                    $id_shop_list[] = $shop;
                }
            }
        }

        if (isset($info['id_product']) && $info['id_product']) {
            $product = new Product((int) $info['id_product'], false, $default_language);
        } elseif (Tools::getValue('match_ref') && isset($info['product_reference']) && $info['product_reference']) {
            $datas = Db::getInstance()->getRow('
                SELECT p.`id_product`
                FROM `' . _DB_PREFIX_ . 'product` p
                ' . Shop::addSqlAssociation('product', 'p') . '
                WHERE p.`reference` = "' . pSQL($info['product_reference']) . '"
            ', false);
            if (isset($datas['id_product']) && $datas['id_product']) {
                $product = new Product((int) $datas['id_product'], false, $default_language);
            } else {
                return;
            }
        } else {
            return;
        }

        $id_image = [];

        if (isset($info['image_url']) && $info['image_url']) {
            $info['image_url'] = explode($this->multiple_value_separator, $info['image_url']);

            if (is_array($info['image_url'])) {
                foreach ($info['image_url'] as $key => $url) {
                    $url = trim($url);
                    $product_has_images = (bool) Image::getImages($this->context->language->id, $product->id);

                    $image = new Image();
                    $image->id_product = (int) $product->id;
                    $image->position = Image::getHighestPosition($product->id) + 1;
                    $image->cover = (!$product_has_images) ? true : false;

                    if (isset($info['image_alt'])) {
                        $alt = self::split($info['image_alt']);
                        if (isset($alt[$key]) && strlen($alt[$key]) > 0) {
                            $alt = self::createMultiLangField($alt[$key]);
                            $image->legend = $alt;
                        }
                    }

                    $field_error = $image->validateFields(UNFRIENDLY_ERROR, true);
                    $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true);

                    if ($field_error === true
                        && $lang_field_error === true
                        && !$validateOnly
                        && $image->add()
                    ) {
                        $image->associateTo($id_shop_list);
                        // FIXME: 2s/image !
                        if (!self::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) {
                            $this->warnings[] = $this->trans(
                                'Error copying image: %url%',
                                ['%url%' => Tools::htmlentitiesUTF8($url)],
                                'Admin.Advparameters.Notification'
                            );
                            $image->delete();
                        } else {
                            $id_image[] = (int) $image->id;
                        }
                    } else {
                        if (!$validateOnly) {
                            $this->warnings[] = $this->trans(
                                '%data% cannot be saved',
                                [
                                    '%data%' => ' (' . Tools::htmlentitiesUTF8($image->id_product) . ')',
                                ],
                                'Admin.Advparameters.Notification'
                            );
                        }
                        if ($field_error !== true || $lang_field_error !== true) {
                            $this->errors[] = ($field_error !== true ? $field_error : '')
                                . ($lang_field_error !== true ? $lang_field_error : '');
                        }
                    }
                }
            }
        } elseif (isset($info['image_position']) && $info['image_position']) {
            $info['image_position'] = explode($this->multiple_value_separator, $info['image_position']);

            if (is_array($info['image_position'])) {
                foreach ($info['image_position'] as $position) {
                    // choose images from product by position
                    $images = $product->getImages($default_language);

                    if ($images) {
                        foreach ($images as $row) {
                            if ($row['position'] == (int) $position) {
                                $id_image[] = (int) $row['id_image'];

                                break;
                            }
                        }
                    }
                    if (empty($id_image)) {
                        $this->warnings[] = sprintf(
                            $this->trans('No image was found for combination with id_product = %s and image position = %s.', [], 'Admin.Advparameters.Notification'),
                            Tools::htmlentitiesUTF8($product->id),
                            (int) $position
                        );
                    }
                }
            }
        }

        $id_attribute_group = 0;
        // groups
        $groups_attributes = [];
        if (isset($info['group'])) {
            foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) {
                if (empty($group)) {
                    continue;
                }
                $tab_group = explode(':', $group);
                $group = trim($tab_group[0]);
                if (!isset($tab_group[1])) {
                    $type = 'select';
                } else {
                    $type = trim($tab_group[1]);
                }

                // sets group
                $groups_attributes[$key]['group'] = $group;

                // if position is filled
                if (isset($tab_group[2])) {
                    $position = trim($tab_group[2]);
                } else {
                    $position = false;
                }

                if (!isset($groups[$group])) {
                    $obj = new AttributeGroup();
                    $obj->is_color_group = false;
                    $obj->group_type = pSQL($type);
                    $obj->name[$default_language] = $group;
                    $obj->public_name[$default_language] = $group;
                    $obj->position = (!$position) ? AttributeGroup::getHigherPosition() + 1 : $position;

                    if ($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true) === true
                        && $lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true) === true
                    ) {
                        // here, cannot avoid attributeGroup insertion to avoid an error during validation step.
                        $obj->add();
                        $obj->associateTo($id_shop_list);
                        $groups[$group] = $obj->id;
                    } else {
                        $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
                    }

                    // fills groups attributes
                    $id_attribute_group = $obj->id;
                    $groups_attributes[$key]['id'] = $id_attribute_group;
                } else {
                    // already exists

                    $id_attribute_group = $groups[$group];
                    $groups_attributes[$key]['id'] = $id_attribute_group;
                }
            }
        }

        // inits attribute
        $id_product_attribute = 0;
        $id_product_attribute_update = false;
        $attributes_to_add = [];

        // for each attribute
        if (isset($info['attribute'])) {
            foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) {
                if (empty($attribute)) {
                    continue;
                }
                $tab_attribute = explode(':', $attribute);
                $attribute = trim($tab_attribute[0]);
                // if position is filled
                if (isset($tab_attribute[1])) {
                    $position = trim($tab_attribute[1]);
                } else {
                    $position = false;
                }

                if (isset($groups_attributes[$key])) {
                    $group = $groups_attributes[$key]['group'];
                    if (!isset($attributes[$group . '_' . $attribute])) {
                        $id_attribute_group = $groups_attributes[$key]['id'];
                        $obj = new ProductAttribute();
                        // sets the proper id (corresponding to the right key)
                        $obj->id_attribute_group = $groups_attributes[$key]['id'];
                        $obj->name[$default_language] = str_replace('\n', '', str_replace('\r', '', $attribute));
                        $obj->position = (!$position && isset($groups[$group])) ? ProductAttribute::getHigherPosition($groups[$group]) + 1 : $position;

                        if ($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true) === true
                            && $lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true) === true
                        ) {
                            if (!$validateOnly) {
                                $obj->add();
                                $obj->associateTo($id_shop_list);
                                $attributes[$group . '_' . $attribute] = $obj->id;
                            }
                        } else {
                            $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '');
                        }
                    }

                    $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int) $info['minimal_quantity'] : 1;
                    $info['low_stock_threshold'] = empty($info['low_stock_threshold']) && '0' != $info['low_stock_threshold'] ? null : (int) $info['low_stock_threshold'];
                    $info['low_stock_alert'] = !empty($info['low_stock_alert']);

                    $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']);
                    $info['price'] = str_replace(',', '.', $info['price']);
                    $info['ecotax'] = str_replace(',', '.', $info['ecotax']);
                    $info['weight'] = str_replace(',', '.', $info['weight']);
                    $info['available_date'] = Validate::isDate($info['available_date']) ? $info['available_date'] : null;

                    if (!Validate::isEan13($info['ean13'])) {
                        $this->warnings[] = $this->trans(
                            'EAN13 "%ean13%" has incorrect value for product with id %id%.',
                            [
                                '%ean13%' => Tools::htmlentitiesUTF8($info['ean13']),
                                '%id%' => Tools::htmlentitiesUTF8($product->id),
                            ],
                            'Admin.Advparameters.Notification'
                        );
                        $info['ean13'] = '';
                    }

                    if ($info['default_on'] && !$validateOnly) {
                        $product->deleteDefaultAttributes();
                    }

                    // if a reference is specified for this product, get the associate id_product_attribute to UPDATE
                    if (isset($info['reference']) && !empty($info['reference'])) {
                        $id_product_attribute = Combination::getIdByReference($product->id, (string) $info['reference']);

                        // updates the attribute
                        if ($id_product_attribute && !$validateOnly) {
                            // gets all the combinations of this product
                            $attribute_combinations = $product->getAttributeCombinations($default_language);
                            foreach ($attribute_combinations as $attribute_combination) {
                                if (in_array($id_product_attribute, $attribute_combination)) {
                                    // FIXME: ~3s/declinaison
                                    $product->updateAttribute(
                                        $id_product_attribute,
                                        (float) $info['wholesale_price'],
                                        (float) $info['price'],
                                        (float) $info['weight'],
                                        0,
                                        Configuration::get('PS_USE_ECOTAX') ? (float) $info['ecotax'] : 0,
                                        $id_image,
                                        (string) $info['reference'],
                                        (string) $info['ean13'],
                                        (bool) $info['default_on'] == true ? (bool) $info['default_on'] : null,
                                        '',
                                        (string) $info['upc'],
                                        (int) $info['minimal_quantity'],
                                        $info['available_date'],
                                        false,
                                        $id_shop_list,
                                        '',
                                        $info['low_stock_threshold'],
                                        $info['low_stock_alert']
                                    );
                                    $id_product_attribute_update = true;
                                    if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) {
                                        $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']);
                                    }
                                    // until here
                                }
                            }
                        }
                    }

                    // if no attribute reference is specified, creates a new one
                    if (!$id_product_attribute && !$validateOnly) {
                        $id_product_attribute = $product->addCombinationEntity(
                            (float) $info['wholesale_price'],
                            (float) $info['price'],
                            (float) $info['weight'],
                            0,
                            Configuration::get('PS_USE_ECOTAX') ? (float) $info['ecotax'] : 0,
                            (int) $info['quantity'],
                            $id_image,
                            (string) $info['reference'],
                            0,
                            (string) $info['ean13'],
                            (bool) $info['default_on'] === true ? (bool) $info['default_on'] : null,
                            '',
                            (string) $info['upc'],
                            (int) $info['minimal_quantity'],
                            $id_shop_list,
                            $info['available_date'],
                            '',
                            $info['low_stock_threshold'],
                            $info['low_stock_alert']
                        );

                        if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) {
                            $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']);
                        }
                    }

                    // fills our attributes array, in order to add the attributes to the product_attribute afterwards
                    if (isset($attributes[$group . '_' . $attribute])) {
                        $attributes_to_add[] = (int) $attributes[$group . '_' . $attribute];
                    }

                    // after insertion, we clean attribute position and group attribute position
                    if (!$validateOnly) {
                        $obj = new ProductAttribute();
                        $obj->cleanPositions((int) $id_attribute_group, false);
                        AttributeGroup::cleanPositions();
                    }
                }
            }
        }

        $product->checkDefaultAttributes();
        if (!$product->cache_default_attribute && !$validateOnly) {
            Product::updateDefaultAttribute($product->id);
        }
        if ($id_product_attribute) {
            if (!$validateOnly) {
                // now adds the attributes in the attribute_combination table
                if ($id_product_attribute_update) {
                    Db::getInstance()->execute('
                        DELETE FROM ' . _DB_PREFIX_ . 'product_attribute_combination
                        WHERE id_product_attribute = ' . (int) $id_product_attribute);
                }

                foreach ($attributes_to_add as $attribute_to_add) {
                    Db::getInstance()->execute('
                        INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute)
                        VALUES (' . (int) $attribute_to_add . ',' . (int) $id_product_attribute . ')', false);
                }
            }

            // set advanced stock managment
            if (isset($info['advanced_stock_management'])) {
                if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management has incorrect value. Not set for product with id %id%.',
                        [
                            '%id%' => Tools::htmlentitiesUTF8($product->id),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, cannot enable on product with id %id%.',
                        [
                            '%id%' => Tools::htmlentitiesUTF8($product->id),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!$validateOnly) {
                    $product->setAdvancedStockManagement($info['advanced_stock_management']);
                }
                // automaticly disable depends on stock, if a_s_m set to disabled
                if (!$validateOnly && StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) {
                    StockAvailable::setProductDependsOnStock($product->id, false, null, $id_product_attribute);
                }
            }

            // Check if warehouse exists
            if (isset($info['warehouse']) && $info['warehouse']) {
                if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, warehouse is not set on product with id %id%.',
                        ['%id%' => Tools::htmlentitiesUTF8($product->id)],
                        'Admin.Advparameters.Notification'
                    );
                } else {
                    if (Warehouse::exists($info['warehouse'])) {
                        $warehouse_location_entity = new WarehouseProductLocation();
                        $warehouse_location_entity->id_product = $product->id;
                        $warehouse_location_entity->id_product_attribute = $id_product_attribute;
                        $warehouse_location_entity->id_warehouse = $info['warehouse'];
                        if (!$validateOnly) {
                            if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) {
                                $warehouse_location_entity->update();
                            } else {
                                $warehouse_location_entity->save();
                            }
                            StockAvailable::synchronize($product->id);
                        }
                    } else {
                        $this->warnings[] = $this->trans(
                            'Warehouse did not exist, cannot set on product %name%.',
                            [
                                '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language]),
                            ],
                            'Admin.Advparameters.Notification'
                        );
                    }
                }
            }

            // stock available
            if (isset($info['depends_on_stock'])) {
                if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) {
                    $this->warnings[] = $this->trans(
                        'Incorrect value for "Depends on stock" for product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language]),
                        ],
                        'Admin.Notifications.Error'
                    );
                } elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) {
                    $this->warnings[] = $this->trans(
                        'Advanced stock management is not enabled, cannot set "Depends on stock" for product %name%',
                        [
                            '%name%' => Tools::htmlentitiesUTF8($product->name[$default_language]),
                        ],
                        'Admin.Advparameters.Notification'
                    );
                } elseif (!$validateOnly) {
                    StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute);
                }

                // This code allows us to set qty and disable depends on stock
                if (isset($info['quantity'])) {
                    // if depends on stock and quantity, add quantity to stock
                    if ($info['depends_on_stock'] == 1) {
                        $stock_manager = StockManagerFactory::getManager();
                        $price = str_replace(',', '.', $info['wholesale_price']);
                        if ($price == '0') {
                            $price = 0.000001;
                        }
                        $price = round((float) $price, 6);
                        $warehouse = new Warehouse($info['warehouse']);
                        if (!$validateOnly && $stock_manager->addProduct((int) $product->id, $id_product_attribute, $warehouse, (int) $info['quantity'], 1, $price, true)) {
                            StockAvailable::synchronize((int) $product->id);
                        }
                    } elseif (!$validateOnly) {
                        if ($shop_is_feature_active) {
                            foreach ($id_shop_list as $shop) {
                                StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop);
                            }
                        } else {
                            StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id);
                        }
                    }
                }
            } elseif (!$validateOnly) { // if not depends_on_stock set, use normal qty
                if ($shop_is_feature_active) {
                    foreach ($id_shop_list as $shop) {
                        StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop);
                    }
                } else {
                    StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id);
                }
            }

            // assign combination id to already associated product suppliers
            $productSuppliers = ProductSupplier::getSupplierCollection($product->id);
            /** @var ProductSupplier $productSupplier */
            foreach ($productSuppliers as $productSupplier) {
                // skip if related combination supplier already exists
                if ((int) $productSupplier->id_product_attribute === (int) $id_product_attribute) {
                    continue;
                }

                $combinationSupplier = clone $productSupplier;
                $combinationSupplier->id = null;
                $combinationSupplier->id_product_attribute = $id_product_attribute;
                $combinationSupplier->add();
            }
        }
    }

    public function utf8EncodeArray($value)
    {
        if (!is_array($value)) {
            return mb_convert_encoding($value, 'UTF-8', mb_detect_encoding($value));
        }

        return array_map(
            function ($item) {
                return mb_convert_encoding($item, 'UTF-8', mb_detect_encoding($item));
            },
            $value
        );
    }

    protected function getNbrColumn($handle, $glue)
    {
        if (!is_resource($handle)) {
            return false;
        }
        $tmp = fgetcsv($handle, MAX_LINE_SIZE, $glue);
        self::rewindBomAware($handle);

        return count($tmp);
    }

    protected static function usortFiles($a, $b)
    {
        if ($a == $b) {
            return 0;
        }

        return ($b < $a) ? 1 : -1;
    }

    protected function openCsvFile($offset = false)
    {
        $file = $this->excelToCsvFile(Tools::getValue('csv'));
        $handle = false;
        if (is_file($file) && is_readable($file)) {
            if (!mb_check_encoding(Tools::file_get_contents($file), 'UTF-8')) {
                $this->convert = true;
            }
            $handle = fopen($file, 'rb');
        }

        if (!$handle) {
            $this->errors[] = $this->trans('Cannot read the .CSV file', [], 'Admin.Advparameters.Notification');

            return null; // error case
        }

        self::rewindBomAware($handle);

        $toSkip = (int) Tools::getValue('skip');
        if ($offset && $offset > 0) {
            $toSkip += $offset;
        }
        for ($i = 0; $i < $toSkip; ++$i) {
            $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator);
            if ($line === false) {
                return false; // reached end of file
            }
        }

        return $handle;
    }

    protected function closeCsvFile($handle)
    {
        fclose($handle);
    }

    protected function excelToCsvFile($filename)
    {
        if (preg_match('#(.*?)\.(csv)#is', $filename)) {
            $dest_file = $this->getPath((string) preg_replace('/\.{2,}/', '.', $filename));
        } else {
            $csv_folder = $this->getPath();
            $excel_folder = $csv_folder . 'csvfromexcel/';
            $info = pathinfo($filename);
            $csv_name = basename($filename, '.' . $info['extension']) . '.csv';
            $dest_file = $excel_folder . $csv_name;

            if (!is_dir($excel_folder)) {
                mkdir($excel_folder);
            }

            if (!is_file($dest_file)) {
                $reader_excel = IOFactory::createReaderForFile($csv_folder . $filename);
                $reader_excel->setReadDataOnly(true);
                $excel_file = $reader_excel->load($csv_folder . $filename);

                /** @var Csv $csv_writer */
                $csv_writer = IOFactory::createWriter($excel_file, 'Csv');

                $csv_writer->setSheetIndex(0);
                $csv_writer->setDelimiter(';');
                $csv_writer->save($dest_file);
            }
        }

        return $dest_file;
    }

    protected function truncateTables()
    {
        if (!$this->sellerinfo || !$this->sellerinfo->getIdSellerinfo()) {
            return;
        }

        $sellerinfoProductRepository = $this->entityManager->getRepository(SellerinfoProduct::class);

        $idsProduct = [];

        foreach ($sellerinfoProductRepository->findBy(['sellerInfo' => $this->sellerinfo]) as $sellerinfoProduct) {
            $idsProduct[] = $sellerinfoProduct->getIdProduct();
        }
        if (count($idsProduct)) {
            $idsProduct = implode(
                ',',
                array_map(
                    function ($id) {
                        return (int) $id;
                    },
                    $idsProduct
                )
            );

            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_shop` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'feature_product` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_lang` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'category_product` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_tag` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'specific_price` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'specific_price_priority` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_carrier` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'cart_product` WHERE id_product IN (' . $idsProduct . ')');

            if (count(Db::getInstance()->executeS('SHOW TABLES LIKE \'' . _DB_PREFIX_ . 'favorite_product\' '))) {
                Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'favorite_product` WHERE id_product IN (' . $idsProduct . ')');
            }

            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_attachment` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_country_tax` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_download` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_group_reduction_cache` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_sale` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_supplier` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'warehouse_product_location` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customization` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'customization_field` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'supply_order_detail` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'pack` WHERE id_product_pack IN (' . $idsProduct . ') OR  id_product_item IN (' . $idsProduct . ')');

            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_attribute_shop` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_attribute_combination` WHERE id_product_attribute IN (SELECT id_product_attribute FROM ' . _DB_PREFIX_ . 'product_attribute WHERE id_product IN (' . $idsProduct . '))');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_attribute_image` WHERE id_product_attribute IN (SELECT id_product_attribute FROM ' . _DB_PREFIX_ . 'product_attribute WHERE id_product IN (' . $idsProduct . '))');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'product_attribute` WHERE id_product IN (' . $idsProduct . ')');

            $idsStock = 'SELECT id_stock FROM `' . _DB_PREFIX_ . 'stock` WHERE id_product IN (' . $idsProduct . ')';
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'stock_mvt` WHERE id_stock IN (' . $idsStock . ')');

            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'stock_available` WHERE id_product IN (' . $idsProduct . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'stock` WHERE id_product IN (' . $idsProduct . ')');

            $idsImage = 'SELECT id_image FROM `' . _DB_PREFIX_ . 'image` WHERE id_product IN (' . $idsProduct . ')';
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'image_lang` WHERE id_image IN (' . $idsImage . ')');
            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'image_shop` WHERE id_image IN (' . $idsImage . ')');

            Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'image` WHERE id_product IN (' . $idsProduct . ')');

            Db::getInstance()->execute('DELETE FROM ' . _DB_PREFIX_ . 'sellerinfo_product WHERE id_sellerinfo =' . (int) $this->sellerinfo->getIdSellerinfo());

            if (!file_exists(_PS_PRODUCT_IMG_DIR_)) {
                mkdir(_PS_PRODUCT_IMG_DIR_);
            }
        }
    }

    public function clearSmartyCache()
    {
        Tools::enableCache();
        Tools::clearCache($this->context->smarty);
        Tools::restoreCacheSettings();
    }

    public function postProcess()
    {
        /* PrestaShop demo mode */
        if (_PS_MODE_DEMO_) {
            $this->errors[] = $this->trans('This functionality has been disabled.', [], 'Admin.Notifications.Error');

            return;
        }

        if (Tools::isSubmit('import')) {
            $this->importExecuted = true;
            $this->importByGroups();
        } elseif ($filename = Tools::getValue('csvfilename')) {
            $filename = urldecode($filename);
            $file = $this->getPath(basename($filename));
            if (realpath(dirname($file)) != realpath($this->getPath())) {
                exit;
            }
            if (!empty($filename)) {
                $b_name = basename($filename);

                if (Tools::getValue('delete')) {
                    if (file_exists($file)) {
                        @unlink($file);
                    }

                    $filename = 'csvfromexcel/' . basename($b_name, '.xls') . '.csv';
                    $file = $this->getPath($filename);
                    if (file_exists($file)) {
                        @unlink($file);
                    }

                    $filename = 'csvfromexcel/' . basename($b_name, '.xlsx') . '.csv';
                    $file = $this->getPath($filename);
                    if (file_exists($file)) {
                        @unlink($file);
                    }
                } elseif (file_exists($file)) {
                    $b_name = explode('.', $b_name);
                    $b_name = strtolower($b_name[count($b_name) - 1]);
                    $mime_types = ['csv' => 'text/csv'];

                    if (isset($mime_types[$b_name])) {
                        $mime_type = $mime_types[$b_name];
                    } else {
                        $mime_type = 'application/octet-stream';
                    }

                    if (ob_get_level() && ob_get_length() > 0) {
                        ob_end_clean();
                    }

                    header('Content-Transfer-Encoding: binary');
                    header('Content-Type: ' . $mime_type);
                    header('Content-Length: ' . filesize($file));
                    header('Content-Disposition: attachment; filename="' . $filename . '"');
                    $fp = fopen($file, 'rb');
                    while (is_resource($fp) && !feof($fp)) {
                        echo fgets($fp, 16384);
                    }
                    exit;
                }
            }
        }
        Db::getInstance()->enableCache();

        return parent::postProcess();
    }

    public function importByGroups($offset = false, $limit = false, &$results = null, $validateOnly = false, $moreStep = 0)
    {
        // Check if the CSV file exist
        if (Tools::getValue('csv')) {
            $shop_is_feature_active = Shop::isFeatureActive();
            // If i am a superadmin, i can truncate table (ONLY IF OFFSET == 0 or false and NOT FOR VALIDATION MODE!)
            if (!$offset && !$moreStep && !$validateOnly && ($shop_is_feature_active || !$shop_is_feature_active) && Tools::getValue('truncate')) {
                $this->truncateTables();
            }
            $import_type = false;
            $doneCount = 0;
            /** @var array<string> $moreStepLabels */
            $moreStepLabels = [];
            // Sometime, import will use registers to memorize data across all elements to import (for trees, or else).
            // Since import is splitted in multiple ajax calls, we must keep these data across all steps of the full import.
            $crossStepsVariables = [];
            if ($crossStepsVars = Tools::getValue('crossStepsVars')) {
                $crossStepsVars = json_decode($crossStepsVars, true);
                if (count($crossStepsVars) > 0) {
                    $crossStepsVariables = $crossStepsVars;
                }
            }
            Db::getInstance()->disableCache();
            $clearCache = false;
            switch ((int) Tools::getValue('entity')) {
                case $this->entities[$import_type = $this->trans('Products', [], 'Admin.Global')]:
                    if (!defined('PS_MASS_PRODUCT_CREATION')) {
                        define('PS_MASS_PRODUCT_CREATION', true);
                    }
                    $moreStepLabels = [$this->trans('Linking Accessories...', [], 'Admin.Advparameters.Notification')];
                    $doneCount += $this->productImport($offset, $limit, $crossStepsVariables, $validateOnly, $moreStep);
                    $clearCache = true;

                    break;
            }

            if ($results !== null) {
                $results['isFinished'] = ($doneCount < $limit);
                if ($results['isFinished'] && $clearCache && !$validateOnly) {
                    $this->clearSmartyCache();
                }
                $results['doneCount'] = $offset + $doneCount;
                if ($offset === 0) {
                    // compute total count only once, because it takes time
                    $handle = $this->openCsvFile(0);
                    if ($handle) {
                        $count = 0;
                        while (fgetcsv($handle, MAX_LINE_SIZE, $this->separator)) {
                            ++$count;
                        }
                        $results['totalCount'] = $count;
                    }
                    $this->closeCsvFile($handle);
                }
                if (!$results['isFinished'] || (!$validateOnly && ($moreStep < count($moreStepLabels)))) {
                    // Since we'll have to POST this array from ajax for the next call, we should care about it size.
                    $nextPostSize = mb_strlen(json_encode($crossStepsVariables));
                    $results['crossStepsVariables'] = $crossStepsVariables;
                    $results['nextPostSize'] = $nextPostSize + (1024 * 64); // 64KB more for the rest of the POST query.
                    $results['postSizeLimit'] = Tools::getMaxUploadSize();
                }
                if ($results['isFinished'] && !$validateOnly && ($moreStep < count($moreStepLabels))) {
                    $results['oneMoreStep'] = $moreStep + 1;
                    $results['moreStepLabel'] = $moreStepLabels[$moreStep];
                }
            }

            Db::getInstance()->enableCache();
        } else {
            $this->errors[] = $this->trans('To proceed, please upload a file first.', [], 'Admin.Advparameters.Notification');
        }
    }

    public static function setLocale()
    {
        $iso_lang = trim(Tools::getValue('iso_lang'));
        setlocale(LC_COLLATE, strtolower($iso_lang) . '_' . strtoupper($iso_lang) . '.UTF-8');
        setlocale(LC_CTYPE, strtolower($iso_lang) . '_' . strtoupper($iso_lang) . '.UTF-8');
    }

    protected function addProductWarning($product_name, $product_id = null, $message = '')
    {
        $this->warnings[] = Tools::htmlentitiesUTF8(
            $product_name
            . (isset($product_id) ? ' (ID ' . $product_id . ')' : '')
            . ' '
            . $message
        );
    }

    public function displayAjaxSaveImportMatchs()
    {
        $match = implode('|', Tools::getValue('type_value'));
        Db::getInstance()->execute('INSERT IGNORE INTO  `' . _DB_PREFIX_ . 'import_match` (
                                    `id_import_match` ,
                                    `name` ,
                                    `match`,
                                    `skip`
                                    )
                                    VALUES (
                                    NULL ,
                                    \'' . pSQL(Tools::getValue('newImportMatchs')) . '\',
                                    \'' . pSQL($match) . '\',
                                    \'' . pSQL(Tools::getValue('skip')) . '\'
                                    )', false);

        $idImportMatch = Db::getInstance()->Insert_ID();

        Db::getInstance()->execute('INSERT IGNORE INTO  `' . _DB_PREFIX_ . 'sellerinfo_import_match` (
                `id_sellerinfo` ,
                `id_import_match`
            )
            VALUES (
                ' . (int) $this->sellerinfo->getIdSellerinfo() . ',
                ' . (int) $idImportMatch . '
            )',
            false);

        exit('{"id" : "' . $idImportMatch . '"}');
    }

    public function displayAjaxLoadImportMatchs()
    {
        $return = Db::getInstance()->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'import_match` WHERE `id_import_match` = '
            . (int) Tools::getValue('idImportMatchs'), true, false);
        exit('{"id" : "' . $return[0]['id_import_match'] . '", "matchs" : "' . $return[0]['match'] . '", "skip" : "'
            . $return[0]['skip'] . '"}');
    }

    public function displayAjaxDeleteImportMatchs()
    {
        $id_import_match = (int) Tools::getValue('idImportMatchs');

        Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'import_match` WHERE `id_import_match` = '
            . (int) $id_import_match, false);
        Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'sellerinfo_import_match` WHERE `id_import_match` = '
        . (int) $id_import_match . ' AND id_sellerinfo = ' . (int) $this->sellerinfo->getIdSellerinfo(), false);

        echo json_encode([
            'success' => true,
        ]);
        exit;
    }

    public function getPath($file = '')
    {
        $idSellerinfo = (int) $this->sellerinfo->getIdSellerinfo();
        $path = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'agilemultisellerpro' . DIRECTORY_SEPARATOR . 'import';

        if (!file_exists($path)) {
            mkdir($path);
        }

        $path .= DIRECTORY_SEPARATOR . $idSellerinfo;

        if (!file_exists($path)) {
            mkdir($path);
        }

        return $path . DIRECTORY_SEPARATOR . $file;
    }

    protected function addSellerInfoCategory($idCategory)
    {
        $sellerInfoCategoryRepository = $this->entityManager->getRepository(SellerinfoCategory::class);

        $sellerInfoCategory = $sellerInfoCategoryRepository
            ->findOneBy(['sellerInfo' => $this->sellerinfo, 'idCategory' => (int) $idCategory]);

        if (!$sellerInfoCategory) {
            $sellerInfoCategory = new SellerinfoCategory();

            $sellerInfoCategory->setSellerinfo($this->sellerinfo)
                ->setIdCategory((int) $idCategory);

            $this->entityManager->persist($sellerInfoCategory);
            $this->entityManager->flush();
        }
    }

    public function displayAjaxImportProducts()
    {
        $offset = (int) Tools::getValue('offset');
        $limit = 10;
        $status = true;
        $results = [];

        $this->importExecuted = true;
        $this->importByGroups($offset, $limit, $results);

        if (false === $this->isProductLimit) {
            $status = false;
        }

        $this->ajaxRender(json_encode([
            'status' => $status,
            'errors' => $this->errors,
            'offset' => $offset,
            'results' => $results,
        ]));

        exit;
    }

    private function isProductLimitError()
    {
        $sellerinfoMembershipType = $this->getSellerinfoMembershipType();

        $sellerinfoProductRepository = $this->entityManager->getRepository(SellerinfoProduct::class);

        $numberSellerProducts = $sellerinfoProductRepository->getCountProducts($this->sellerinfo);

        if (
            (int) $numberSellerProducts >= (int) $sellerinfoMembershipType->getListingMax()
            && $sellerinfoMembershipType->getListingMax() != 0
        ) {
            return false;
        }

        return true;
    }

    private function getSellerinfoMembershipType()
    {
        if (!$this->sellerinfoMembershipType) {
            $idCustomer = $this->sellerinfo->getIdCustomer();

            $sellerInfoMembershipCustomerRepository = $this->entityManager
                ->getRepository(SellerinfoMembershipCustomer::class);

            $sellerInfoMembershipCustomer = $sellerInfoMembershipCustomerRepository
                ->findOneBy(['idCustomer' => $idCustomer]);

            if (!$sellerInfoMembershipCustomer) {
                return new SellerinfoMembershipType();
            }

            $idMembershipType = $sellerInfoMembershipCustomer->getSellerinfoMembershipType()
                ->getIdMembershipType();

            $sellerinfoMembershipTypeRepository = $this->entityManager->getRepository(SellerinfoMembershipType::class);

            $this->sellerinfoMembershipType = $sellerinfoMembershipTypeRepository->findOneBy([
                'idMembershipType' => $idMembershipType,
            ]);
        }

        return $this->sellerinfoMembershipType;
    }
}
