<?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
 */
if (!defined('_PS_VERSION_')) {
    exit;
}

use PrestaShop\Module\AgileMultisellerPro\Controller\Front\AgileModuleFrontController;
use PrestaShop\Module\AgileMultisellerPro\Entity\SellerinfoAttachment;
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;
use PrestaShop\Module\AgileMultisellerPro\Helper\Form\ProductForm;

class AgileMultiSellerProSellerProductDetailModuleFrontController extends AgileModuleFrontController
{
    protected $product_menus = [];
    public $auth = true;
    public $ssl = true;
    protected $languages;
    protected $id_language;
    protected $product_menu;
    protected $object;

    const UNFRIENDLY_ERROR = false;

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

        $this->product_menus[] = ['id' => 1, 'name' => $this->trans('Required data', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 12, 'name' => $this->trans('Description and Seo', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 2, 'name' => $this->trans('Images', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 3, 'name' => $this->trans('Features', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 4, 'name' => $this->trans('Extra categories', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 5, 'name' => $this->trans('Prices (Discounts)', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 6, 'name' => $this->trans('Quantity (Stock)', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 7, 'name' => $this->trans('Combinations', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 8, 'name' => $this->trans('Virtual Product', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 9, 'name' => $this->trans('Shipping', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 10, 'name' => $this->trans('Attachments', [], 'Modules.Agilemultisellerpro.Product')];
        $this->product_menus[] = ['id' => 13, 'name' => $this->trans('Options', [], 'Modules.Agilemultisellerpro.Product')];

        if (Module::isInstalled('agileproducttags')
            && Module::isEnabled('agileproducttags')
            && Configuration::get('ALLOW_SELLER_ATTACH_TAGS')
        ) {
            $this->product_menus[] = ['id' => 11, 'name' => $this->trans('Product Tags', [], 'Modules.Agilemultisellerpro.Product')];
        }

        $this->table = 'product';
        $this->identifier = 'id_product';
        $this->className = 'Product';
    }

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

        $deflang = new Language($this->context->language->id);
        $isoTinyMCE = (file_exists(_PS_ROOT_DIR_ . '/js/tiny_mce/langs/' . $deflang->iso_code .
            '.js') ? $deflang->iso_code : 'en');

        Media::addJsDef([
            'iso' => $isoTinyMCE,
            'ad' => str_replace('\\', '\\\\', dirname($_SERVER['PHP_SELF'])),
            'id_language_current' => $this->context->language->id,
            'allowCopyMainStoreProduct' => (int) Configuration::get('AGILE_MS_PRODUCT_COPY'),
            'agileProductId' => (int) $this->object->id,
        ]);

        $this->addJqueryPlugin([
            'tagify',
            'tablednd',
            'ajaxfileupload',
            'growl',
            'autocomplete',
        ]);

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

        $this->registerStylesheet(
            'agile_treeview_categories',
            '/modules/agilemultisellerpro/views/css/jquery.treeview-categories.css',
            ['media' => 'all', 'priority' => 100]
        );

        $this->registerStylesheet(
            'agile_product_detail',
            '/modules/agilemultisellerpro/views/css/front/product.detail.css',
            ['media' => 'all', 'priority' => 100]
        );

        $this->registerStylesheet(
            'agile_editable',
            '/modules/agilemultisellerpro/views/css/plugins/editable/bootstrap-editable.css',
            ['media' => 'all', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile_editable',
            '/modules/agilemultisellerpro/views/js/plugins/editable/bootstrap-editable.min.js',
            ['position' => 'bottom', 'priority' => 100]
        );

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

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

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

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

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

        $this->registerJavascript(
            'agile_treeview_categotiessync',
            '/modules/agilemultisellerpro/views/js/front/treeview-categories/jquery.treeview-categories.async.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile_treeview_categotiesedit',
            '/modules/agilemultisellerpro/views/js/front/treeview-categories/jquery.treeview-categories.edit.js',
            ['position' => 'bottom', 'priority' => 100]
        );

        $this->registerJavascript(
            'agile_multilanguage',
            '/modules/agilemultisellerpro/views/js/multi-language.js',
            ['position' => 'bottom', 'priority' => 100]
        );

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

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

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

        $this->languages = Language::getLanguages(false);
        $this->id_language = (int) Tools::getValue('id_language');
        $this->product_menu = (int) Tools::getValue('product_menu');
        $id_product = (int) Tools::getValue('id_product');

        if ($id_product === 0) {
            $sellerinfoMembershipType = $this->getSellerinfoMembershipType();

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

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

            if (
                (int) $numberSellerProducts >= (int) $sellerinfoMembershipType->getListingMax()
                && $sellerinfoMembershipType->getListingMax() != 0
            ) {
                $this->context->cookie->__set(
                    'membership_product_limit_error',
                    $this->trans(
                        'The subscription plan limit has been reached! Please order a new plan or upgrade your current one!',
                        [],
                        'Modules.Agilemultisellerpro.Product'
                    ),
                );

                Tools::redirect($this->context->link->getModuleLink($this->module->name, 'sellerproducts'));
            }
        }

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

        if ($this->id_language == 0) {
            $this->id_language = $this->context->language->id;
        }

        $this->object = new Product($id_product, false);

        if (Tools::getValue('action') == 'getVirtualFile') {
            $this->getVirtualFile();
        }

        if ((int) $this->object->id_manufacturer == 0) {
            $this->object->id_manufacturer = $this->sellerinfo->getIdManufacturer();
        }

        if ((int) $this->object->id_supplier == 0) {
            $this->object->id_supplier = $this->sellerinfo->getIdSupplier();
        }

        if ($this->object->id == 0) {
            $this->object->out_of_stock = StockAvailable::outOfStock(0);
        }

        $hasOwnerShip = $this->hasOwnerShip();

        if (!$hasOwnerShip) {
            $this->errors[] = $this->trans('You do not have permission to access/modify this data.', [], 'Modules.Agilemultisellerpro.Product');
        }

        $this->context->smarty->assign([
            'hasOwnerShip' => $hasOwnerShip,
            'PS_ALLOW_ACCENTED_CHARS_URL' => (int) Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL'),
            'ps_force_friendly_product' => (int) Configuration::get('PS_FORCE_FRIENDLY_PRODUCT'),
            'currency' => $this->context->currency,
        ]);
    }

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

        $this->initContentCommon();

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

    private function initContentCommon()
    {
        $this->context->smarty->assign([
            'seller_tab_id' => 3,
            'languages' => Language::getLanguages(true),
            'product_menus' => $this->product_menus,
            'product_menu' => $this->product_menu,
            'id_language' => $this->id_language,
            'id_product' => $this->object->id,
            'id_category_default' => $this->object->id_category_default,
            'product' => $this->object,
            'id_language_current' => $this->context->language->id,
            'product_type' => (int) Tools::getValue('type_product', $this->object->getType()),
            'defaultCurrency' => Currency::getDefaultCurrency(),

            'formFields' => (new ProductForm($this->sellerinfo, $this->object, $this->entityManager))->makeForm($this->product_menu),
        ]);

        if ($this->product_menu == 4) {
            $sellerCategories = $this->entityManager->getRepository(SellerinfoCategory::class)
            ->getSellerCategories($this->sellerinfo->getIdSellerinfo());

            Media::addJsDef(['sellerCategories' => array_keys($sellerCategories)]);
        }
    }

    private function hasOwnerShip()
    {
        if (
            $this->object->id > 0
            && (
                !Validate::isLoadedObject($this->object)
                || !$this->entityManager->getRepository(SellerinfoProduct::class)
                        ->findOneBy(['sellerInfo' => $this->sellerinfo, 'idProduct' => $this->object->id])
            )
        ) {
            return false;
        }

        return true;
    }

    public function postProcess()
    {
        $this->object->indexed = 0;

        if (Tools::isSubmit('submitTabProduct')) {
            $submitProductMenu = Tools::getValue('submitTabProduct');

            if (isset(ProductForm::PRODUCT_MENU[$submitProductMenu])) {
                $methodSubmit = 'processSubmit' . ucfirst(ProductForm::PRODUCT_MENU[$submitProductMenu]);

                if (true === method_exists($this, $methodSubmit)) {
                    $this->$methodSubmit();

                    if (empty($this->errors)) {
                        $this->context->smarty->assign('cfmmsg_flag', 1);
                    }
                }
            }
        }

        if (empty($this->errors)) {
            if (Validate::isLoadedObject($this->object) && $this->object->update()) {
                if (in_array($this->object->visibility, ['both', 'search']) && Configuration::get('PS_SEARCH_INDEXATION')) {
                    Search::indexation(false, $this->object->id);
                }
            }
        }
    }

    protected function processSubmitInformations()
    {
        $languages = Language::getLanguages(true);

        foreach ($languages as $language) {
            if (empty(Tools::getValue('name_' . $language['id_lang']))) {
                $this->errors[] = $this->trans('Name required in langauge:', [], 'Modules.Agilemultisellerpro.Product')
                    . $language['name'];
            }

            if (empty(Tools::getValue('link_rewrite_' . $language['id_lang']))) {
                $this->object->link_rewrite[$language['id_lang']] = Tools::link_rewrite(Tools::getValue('name_' . $language['id_lang']));
            }
        }

        $this->copyFromPost($this->object, $this->table);

        $this->validateRules();

        if (count($this->errors) > 0) {
            return;
        }

        if ($this->object->id <= 0) {
            if (method_exists($this->object, 'add') && !$this->object->add()) {
                $this->errors[] = $this->trans('An error occurred while creating object.', [], 'Modules.Agilemultisellerpro.Product') .
                    ' ' . $this->table . ' (' . Db::getInstance()->getMsgError() . ') ';
                return;
            }

            $this->updateAssoShop($this->object->id);
            StockAvailable::setQuantity($this->object->id, 0, (int) Tools::getValue('quantity'));
            $this->updateDefaultCategory($this->object->id_category_default, $this->object->id);

            $languages = Language::getLanguages(false);
            $this->updateTags($languages, $this->object);

            // Add SellerinfoProduct
            $sellerinfoProduct = new SellerinfoProduct();
            $sellerinfoProduct->setSellerinfo($this->sellerinfo)->setIdProduct($this->object->id)->setApproved(true);

            $this->entityManager->persist($sellerinfoProduct);
            $this->entityManager->flush();
        } else {
            if (method_exists($this->object, 'update') && !$this->object->update()) {
                $this->errors[] = $this->tras('An error occurred while updating object.', [], 'Modules.Agilemultisellerpro.Product') .
                    ' ' . $this->table . ' (' . Db::getInstance()->getMsgError() . ') ';
                return;
            }

            StockAvailable::setQuantity($this->object->id, 0, (int) Tools::getValue('quantity'));
            $this->updateDefaultCategory($this->object->id_category_default, $this->object->id);

            $languages = Language::getLanguages(false);
            $this->updateTags($languages, $this->object);
        }

        if ($this->object->id_supplier > 0) {
            $this->object->addSupplierReference($this->object->id_supplier, 0);
        }
    }

    protected function updateAssoShop($id_object)
    {
        if (!Shop::isFeatureActive()) {
            return;
        }

        if (!Shop::isTableAssociated($this->table)) {
            return;
        }

        $assos_data = $this->getSelectedAssoShop($this->table);

        // Get list of shop id we want to exclude from asso deletion
        $exclude_ids = $assos_data;

        foreach (Db::getInstance()->executeS('SELECT id_shop FROM ' . _DB_PREFIX_ . 'shop') as $row) {
            if (!$this->context->employee->hasAuthOnShop($row['id_shop'])) {
                $exclude_ids[] = $row['id_shop'];
            }
        }

        Db::getInstance()->delete($this->table . '_shop', '`' . bqSQL($this->identifier) . '` = ' . (int) $id_object . ($exclude_ids ? ' AND id_shop NOT IN (' . implode(', ', array_map('intval', $exclude_ids)) . ')' : ''));

        $insert = [];
        foreach ($assos_data as $id_shop) {
            $insert[] = [
                $this->identifier => (int) $id_object,
                'id_shop' => (int) $id_shop,
            ];
        }

        return Db::getInstance()->insert($this->table . '_shop', $insert, false, true, Db::INSERT_IGNORE);
    }

    protected function updateDefaultCategory($id_category_default, $id_product)
    {
        $sql = 'REPLACE INTO `' . _DB_PREFIX_ . 'category_product` (id_category,id_product,position) VALUES(' .
            (int) $id_category_default . ',' . (int) $id_product . ',0)';
        Db::getInstance()->execute($sql);
    }

    protected function updateTags($languages, $product)
    {
        $tag_success = true;

        if (!Tag::deleteTagsForProduct((int) $product->id)) {
            $this->errors[] = $this->trans('An error occurred while attempting to delete previous tags.', [], 'Modules.Agilemultisellerpro.Product');
        }

        foreach ($languages as $language) {
            if ($value = Tools::getValue('tags_' . $language['id_lang'])) {
                $tag_success &= Tag::addTags($language['id_lang'], (int) $product->id, $value);
            }
        }

        if (!$tag_success) {
            $this->errors[] = $this->trans('An error occurred while adding tags.', [], 'Modules.Agilemultisellerpro.Product');
        }

        return $tag_success;
    }

    protected function processSubmitAddImages()
    {
        $product = new Product(Tools::getValue('id_product'));

        $productImages = $product->getImages($this->context->language->id);

        $sellerinfoMembershipType = $this->getSellerinfoMembershipType();

        if (
            count($productImages) >= (int) $sellerinfoMembershipType->getProductImages()
            && (int) $sellerinfoMembershipType->getProductImages() != 0
        ) {
            $this->errors[] = $this->trans(
                'You\'ve hit the maximum number of images allowed for upload. You\'ve reached the product image limit.',
                [],
                'Modules.Agilemultisellerpro.Product'
            );
            $url = $this->context->link->getModuleLink($this->module->name, 'mymembership');
            $this->errors[] = implode('', ['<', 'a h', 'ref="', $url, '">', 'Make order', '</', 'a>']);
            return false;
        }

        $allowedExtensions = ['jpeg', 'gif', 'png', 'jpg'];
        $uploader = new FileUploader($allowedExtensions, (int) Configuration::get('PS_PRODUCT_PICTURE_MAX_SIZE'));
        $_GET['id_product'] = Tools::getValue('id_product');
        $result = $uploader->handleUpload();
        if (isset($result['success'])) {
            $obj = new Image((int) $result['success']['id_image']);

            $languages = Language::getLanguages(false);
            foreach ($languages as $language) {
                $obj->legend[(int) $language['id_lang']] = Tools::getValue('legend_' . (int) $language['id_lang']);
            }

            $obj->save();
            $shops = Shop::getContextListShopID();
            $obj->associateTo($shops);
            $json_shops = [];
            foreach ($shops as $id_shop) {
                $json_shops[$id_shop] = true;
            }
            @unlink(_PS_TMP_IMG_DIR_ . 'product_' . (int) $obj->id_product . '.jpg');
            @unlink(_PS_TMP_IMG_DIR_ . 'product_mini_' . (int) $obj->id_product . '.jpg');
        } else {
            $this->errors[] = $result['error'];
        }
    }

    protected function processSubmitUpdateLegends()
    {
        if (Validate::isLoadedObject($product = new Product((int) Tools::getValue('id_product')))) {
            $id_image = (int) Tools::getValue('pk');
            $value = Tools::getValue('value');
            $language_ids = Language::getIDs(false);

            if ($id_image && $value) {
                foreach ($language_ids as $id_lang) {
                    Db::getInstance()->execute('UPDATE ' . _DB_PREFIX_ . 'image_lang SET legend = "' .
                        pSQL($value) . '" WHERE ' . ($id_image ? 'id_image = ' .
                        (int) $id_image : 'EXISTS (SELECT 1 FROM ' . _DB_PREFIX_ . 'image WHERE ' .
                        _DB_PREFIX_ . 'image.id_image = ' . _DB_PREFIX_ .
                        'image_lang.id_image AND id_product = ' . (int) $product->id . ')') .
                        ' AND id_lang = ' . (int) $id_lang);
                }
            }
        }
    }

    protected function processSubmitFeatures()
    {
        if (!Feature::isFeatureActive()) {
            return;
        }

        if (!Validate::isLoadedObject($this->object)) {
            $this->errors[] = $this->trans('Product must be created before adding features.', [], 'Modules.Agilemultisellerpro.Product');
            return;
        }

        $this->object->deleteFeatures();

        $languages = Language::getLanguages(false);

        foreach (Tools::getAllValues() as $key => $val) {
            if (preg_match('/^feature_([0-9]+)_value/i', $key, $match)) {
                if ($val) {
                    $this->object->addFeaturesToDB($match[1], $val);
                } else {
                    if ($default_value = $this->checkFeatures($languages, $match[1])) {
                        $id_value = $this->object->addFeaturesToDB($match[1], 0, 1);
                        foreach ($languages as $language) {
                            if ($cust = Tools::getValue('custom_' . $match[1] . '_' . (int) $language['id_lang'])) {
                                $this->object->addFeaturesCustomToDB($id_value, (int) $language['id_lang'], $cust);
                            } else {
                                $this->object->addFeaturesCustomToDB(
                                    $id_value,
                                    (int) $language['id_lang'],
                                    $default_value
                                );
                            }
                        }
                    }
                }
            }
        }
    }

    protected function checkFeatures($languages, $feature_id)
    {
        $rules = call_user_func(['FeatureValue', 'getValidationRules'], 'FeatureValue');
        $feature = Feature::getFeature((int) Configuration::get('PS_LANG_DEFAULT'), $feature_id);
        $val = 0;

        foreach ($languages as $language) {
            if ($val = Tools::getValue('custom_' . $feature_id . '_' . $language['id_lang'])) {
                $current_language = new Language($language['id_lang']);
                if (Tools::strlen($val) > $rules['sizeLang']['value']) {
                    $this->errors[] = $this->trans('name for feature', [], 'Modules.Agilemultisellerpro.Product') .
                        ' ' . $feature['name'] . ' ' .
                        $this->trans('is too long in', [], 'Modules.Agilemultisellerpro.Product') . ' ' . $current_language->name;
                } elseif (!call_user_func(['Validate', $rules['validateLang']['value']], $val)) {
                    $this->errors[] = $this->trans('Valid name required for feature.', [], 'Modules.Agilemultisellerpro.Product') . ' ' .
                        $feature['name'] . '  ' . $this->trans('in', [], 'Modules.Agilemultisellerpro.Product') . ' ' . $current_language->name;
                }
                if (count($this->errors)) {
                    return 0;
                }
                if ($language['id_lang'] == Configuration::get('PS_LANG_DEFAULT')) {
                    return $val;
                }
            }
        }

        return 0;
    }

    protected function processSubmitAssociations()
    {
        $this->object->updateCategories(Tools::getValue('categoryBox'), true);

        $idCategoryDefault = (int) Tools::getValue('id_category_default');

        $newid = $this->addNewCategory();

        if (!$idCategoryDefault && $newid) {
            $idCategoryDefault = $newid;
        } elseif (!$idCategoryDefault) {
            $idCategoryDefault = Configuration::get(DataConfiguration::AGILE_MS_DEFAULT_CATEGORY);
        }

        $this->object->id_category_default = (int) $idCategoryDefault;
        $this->object->id_manufacturer = (int) Tools::getValue('id_manufacturer');

        if ((int) $this->object->id_category_default <= 0) {
            $this->errors[] = $this->trans('Default category is required', [], 'Modules.Agilemultisellerpro.Product');
            return;
        }

        $this->object->save();
    }

    protected function addNewCategory()
    {
        $new_category = Tools::getValue('new_category');

        if (!$new_category) {
            return;
        }

        $category = Category::searchByPath($this->context->language->id, trim($new_category), $this, 'productCreateCat');

        if (!empty($category['id_category'])) {
            $idcategory = (int) $category['id_category'];

            $this->object->addToCategories($idcategory);

            $this->addSellerInfoCategory($idcategory);

            return $idcategory;
        }

        return 0;
    }

    public function productCreateCat($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)),
                ],
                'Modules.Agilemultisellerpro.Product'
            );

            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(self::UNFRIENDLY_ERROR, true)) !== true
            || ($lang_field_error = $category_to_create->validateFieldsLang(self::UNFRIENDLY_ERROR, true)) !== true
            || !$category_to_create->add()
        ) {
            $this->errors[] = sprintf(
                $this->trans('%1$s (ID: %2$s) cannot be saved', [], 'Modules.Agilemultisellerpro.Product'),
                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();
            }
        }
    }

    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();
        }
    }

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

        return $res;
    }

    protected function processSubmitPrices()
    {
        $this->object->wholesale_price = (float) Tools::getValue('wholesale_price');
        $this->object->price = (float) Tools::getValue('price');

        $unit_price = (float) Tools::getValue('unit_price');
        $this->object->unit_price = (float) $unit_price;

        if ($unit_price != 0) {
            $this->object->unit_price_ratio = $this->object->price / $unit_price;
        } else {
            $this->object->unit_price_ratio = 0;
        }

        $this->object->unity = Tools::getValue('unity');
        $this->object->on_sale = Tools::getValue('on_sale');
        $this->object->id_tax_rules_group = Tools::getValue('id_tax_rules_group');
        $this->object->save();
    }

    protected function processSubmitQuantites()
    {
        $this->copyFromPost($this->object, $this->table);
        $this->object->save();
    }

    protected function processSubmitCombinations()
    {
        if (!Combination::isFeatureActive() || !Tools::getIsset('attribute')) {
            return;
        }

        if (Validate::isLoadedObject($product = $this->object)) {
            if ($this->isProductFieldUpdated('attribute_price')
                && (!Tools::getIsset('attribute_price') || Tools::getIsset('attribute_price') == null)
            ) {
                $this->errors[] = $this->trans('Attribute price required.', [], 'Modules.Agilemultisellerpro.Product');
            }

            if (!Tools::getIsset('attribute_combination_list')
                || Tools::isEmpty(Tools::getValue('attribute_combination_list'))
            ) {
                $this->errors[] = $this->trans('You must add at least one attribute.', [], 'Modules.Agilemultisellerpro.Product');
            }
            // $tempVar = '_POST';
            if (!count($this->errors)) {
                if (Tools::getValue('attribute_default')) {
                    $product->deleteDefaultAttributes();
                }

                if ($id_product_attribute = (int) Tools::getValue('id_product_attribute')) {
                    if ($product->productAttributeExists(
                        Tools::getValue('attribute_combination_list'),
                        (int) $id_product_attribute
                    )) {
                        $this->errors[] = $this->trans('This attribute already exists.', [], 'Modules.Agilemultisellerpro.Product');
                    } else {
                        $product->updateAttribute(
                            (int) $id_product_attribute,
                            $this->isProductFieldUpdated('attribute_wholesale_price') ?
                                Tools::getValue('attribute_wholesale_price') : null,
                            $this->isProductFieldUpdated('attribute_price_impact') ?
                                Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact') :
                                null,
                            $this->isProductFieldUpdated('attribute_weight_impact') ?
                                Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact') :
                                null,
                            $this->isProductFieldUpdated('attribute_unit_impact') ?
                                Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact') :
                                null,
                            $this->isProductFieldUpdated('attribute_ecotax') ?
                                Tools::getValue('attribute_ecotax') : null,
                            Tools::getValue('id_image_attr'),
                            Tools::getValue('attribute_reference'),
                            Tools::getValue('attribute_ean13'),
                            $this->isProductFieldUpdated('attribute_default') ?
                                Tools::getValue('attribute_default') : null,
                            Tools::getValue('attribute_location'),
                            Tools::getValue('attribute_upc'),
                            $this->isProductFieldUpdated('attribute_minimal_quantity') ?
                                Tools::getValue('attribute_minimal_quantity') : null,
                            $this->isProductFieldUpdated('available_date_attribute') ?
                                Tools::getValue('available_date_attribute') : null,
                            false
                        );
                    }
                } else {
                    if ($product->productAttributeExists(Tools::getValue('attribute_combination_list'))) {
                        $this->errors[] = $this->trans('This combination already exists.', [], 'Modules.Agilemultisellerpro.Product');
                    } else {
                        $id_product_attribute = $product->addCombinationEntity(
                            Tools::getValue('attribute_wholesale_price'),
                            (int) Tools::getValue('attribute_price') * (int) Tools::getValue('attribute_price_impact'),
                            (int) Tools::getValue('attribute_weight') * (int) Tools::getValue('attribute_weight_impact'),
                            (int) Tools::getValue('attribute_unity') * (int) Tools::getValue('attribute_unit_impact'),
                            Tools::getValue('attribute_ecotax'),
                            0,
                            Tools::getValue('id_image_attr'),
                            Tools::getValue('attribute_reference'),
                            null,
                            Tools::getValue('attribute_ean13'),
                            Tools::getValue('attribute_default'),
                            Tools::getValue('attribute_location'),
                            Tools::getValue('attribute_upc'),
                            Tools::getValue('attribute_minimal_quantity')
                        );
                    }
                }
                if (!count($this->errors)) {
                    $combination = new Combination((int) $id_product_attribute);
                    $combination->setAttributes(Tools::getValue('attribute_combination_list'));

                    $id_images = Tools::getValue('id_image_attr');
                    if (!empty($id_images)) {
                        $combination->setImages($id_images);
                    }
                    $product->checkDefaultAttributes();
                    if (Tools::getValue('attribute_default')) {
                        Product::updateDefaultAttribute((int) $product->id);
                        if (isset($id_product_attribute)) {
                            $product->cache_default_attribute = (int) $id_product_attribute;
                        }
                        if ($available_date = Tools::getValue('available_date_attribute')) {
                            $product->setAvailableDate($available_date);
                        }
                    }
                }
                if (!count($this->errors)) {
                    if (!$product->cache_default_attribute) {
                        Product::updateDefaultAttribute($product->id);
                    }
                }
            }
        }
    }

    protected function isProductFieldUpdated($field, $id_lang = null)
    {
        static $is_activated = null;

        if (is_null($is_activated)) {
            $is_activated = Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->id_object;
        }

        if (!$is_activated) {
            return true;
        }

        if (is_null($id_lang)) {
            return !empty(Tools::getValue('multishop_check')[$field]);
        } else {
            return !empty(Tools::getValue('multishop_check')[$field][$id_lang]);
        }
    }

    protected function processSubmitVirtualproduct()
    {
        $this->object->is_virtual = (int) Tools::getValue('is_virtual_good');
        $this->object->save($this->object);

        if ($this->object->is_virtual && (int) Tools::getValue('is_virtual_file')) {
            $this->updateDownloadProduct($this->object);
        }
    }

    protected function updateDownloadProduct($product, $edit = 0)
    {
        $is_virtual_file = (int) Tools::getValue('is_virtual_file');

        if ((int) Tools::getValue('is_virtual_good')) {
            if (Tools::getValue('virtual_product_expiration_date')
                && !Validate::isDate(Tools::getValue('virtual_product_expiration_date'))
                && !empty($is_virtual_file)
            ) {
                if (!Tools::getValue('virtual_product_expiration_date')) {
                    $this->errors[] = $this->l('This field expiration date attribute is required.');
                    return false;
                }
            }

            if ($edit == 1) {
                $id_product_download = (int) ProductDownload::getIdFromIdProduct((int) $product->id);
                if (!$id_product_download) {
                    $id_product_download = (int) Tools::getValue('virtual_product_id');
                }
            } else {
                $id_product_download = Tools::getValue('virtual_product_id');
            }

            $is_shareable = Tools::getValue('virtual_product_is_shareable');
            $virtual_product_name = Tools::getValue('virtual_product_name');
            $virtual_product_filename = Tools::getValue('virtual_product_filename');
            $virtual_product_nb_days = Tools::getValue('virtual_product_nb_days');
            $virtual_product_nb_downloable = Tools::getValue('virtual_product_nb_downloable');
            $virtual_product_expiration_date = Tools::getValue('virtual_product_expiration_date');

            if ($virtual_product_filename) {
                $filename = $virtual_product_filename;
            } else {
                $filename = ProductDownload::getNewFilename();
            }

            $download = new ProductDownload((int) $id_product_download);
            $download->id_product = (int) $product->id;
            $download->display_filename = $virtual_product_name;
            $download->filename = $filename;
            $download->date_add = date('Y-m-d H:i:s');
            $download->date_expiration = $virtual_product_expiration_date ?
                $virtual_product_expiration_date . ' 23:59:59' : '';
            $download->nb_days_accessible = (int) $virtual_product_nb_days;
            $download->nb_downloadable = (int) $virtual_product_nb_downloable;
            $download->active = 1;
            $download->is_shareable = (int) $is_shareable;

            if ($download->save()) {
                return true;
            }
        } else {
            if ($edit == 1) {
                $id_product_download = (int) ProductDownload::getIdFromIdProduct((int) $product->id);
                if (!$id_product_download) {
                    $id_product_download = (int) Tools::getValue('virtual_product_id');
                }
            } else {
                $id_product_download = ProductDownload::getIdFromIdProduct($product->id);
            }
            if (!empty($id_product_download)) {
                $product_download = new ProductDownload((int) $id_product_download);
                $product_download->date_expiration = date('Y-m-d H:i:s', time() - 1);
                $product_download->active = 0;
                return $product_download->save();
            }
        }

        return false;
    }

    protected function getVirtualFile()
    {
        $productDownload = new ProductDownload();

        if ($id_product_download = $productDownload->getIdFromIdProduct($this->object->id)) {
            $productDownload = new ProductDownload($id_product_download);
        }

        if ($this->sellerinfo->getIdSellerinfo() && $productDownload->id) {
            $file = _PS_DOWNLOAD_DIR_ . $productDownload->filename;
            $filename = $productDownload->display_filename;

            if (empty($filename)) {
                $filename = 'file';
            }

            if (!file_exists($file)) {
                Tools::redirect('index.php');
            }

            $mimeType = false;
            if (function_exists('finfo_open')) {
                $finfo = @finfo_open(FILEINFO_MIME);
                $mimeType = @finfo_file($finfo, $file);
                @finfo_close($finfo);
            } elseif (function_exists('mime_content_type')) {
                $mimeType = @mime_content_type($file);
            } elseif (function_exists('exec')) {
            }

            if (empty($mimeType)) {
                $mimeType = 'application/octet-stream';
            }

            header('Content-Transfer-Encoding: binary');
            header('Content-Type: ' . $mimeType);
            header('Content-Length: ' . filesize($file));
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            ob_end_flush();
            $fp = fopen($file, 'rb');

            while (!feof($fp)) {
                echo fgets($fp, 16384);
            }

            exit;
        }
    }

    protected function processSubmitShipping()
    {
        if (Validate::isLoadedObject($this->object)) {
            $this->object->width = abs((float) Tools::getValue('width'));
            $this->object->height = abs((float) Tools::getValue('height'));
            $this->object->depth = abs((float) Tools::getValue('depth'));
            $this->object->weight = abs((float) Tools::getValue('weight'));
            $this->object->additional_shipping_cost = abs((float) Tools::getValue('additional_shipping_cost'));

            $carriers = [];

            if (Tools::getValue('carriers')) {
                $carriers = Tools::getValue('carriers');
            }

            $this->object->setCarriers($carriers);

            $this->object->save();
        }
    }

    public function processSubmitAddAttachments()
    {
        $languages = Language::getLanguages(false);
        $is_attachment_name_valid = false;

        foreach ($languages as $language) {
            $attachment_name_lang = Tools::getValue('attachment_name_' . (int) $language['id_lang']);
            if (Tools::strlen($attachment_name_lang) > 0) {
                $is_attachment_name_valid = true;
            }

            if (!Validate::isGenericName(Tools::getValue('attachment_name_' . (int) $language['id_lang']))) {
                $this->errors[] = $this->l('Invalid Name');
            } elseif (Tools::strlen(Tools::getValue('attachment_name_' . (int) $language['id_lang'])) > 32) {
                $this->errors[] = sprintf($this->l('Name is too long (%d chars max).'), 32);
            }
            if (!Validate::isCleanHtml(Tools::getValue('attachment_description_' . (int) $language['id_lang']))) {
                $this->errors[] = $this->l('Invalid description');
            }
        }

        if (!$is_attachment_name_valid) {
            $this->errors[] = $this->l('Attachment name required');
        }

        if (empty($this->errors)) {
            if (isset($_FILES['attachment_file']) && is_uploaded_file($_FILES['attachment_file']['tmp_name'])) {
                if ($_FILES['attachment_file']['size'] > (Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024 * 1024)) {
                    $this->errors[] = sprintf(
                        $this->l('File too large, maximum size allowed: %1$d kB. File size you\'re trying to upload is: %2$d kB.'),
                        Configuration::get('PS_ATTACHMENT_MAXIMUM_SIZE') * 1024,
                        number_format(
                            $_FILES['attachment_file']['size'] / 1024,
                            2,
                            '.',
                            ''
                        )
                    );
                } else {
                    do {
                        $uniqid = sha1(microtime());
                    } while (file_exists(_PS_DOWNLOAD_DIR_ . $uniqid));
                    if (!copy($_FILES['attachment_file']['tmp_name'], _PS_DOWNLOAD_DIR_ . $uniqid)) {
                        $this->errors[] = $this->l('File copy failed');
                    }
                    @unlink($_FILES['attachment_file']['tmp_name']);
                }
            } elseif ((int) $_FILES['attachment_file']['error'] === 1) {
                $max_upload = (int) ini_get('upload_max_filesize');
                $max_post = (int) ini_get('post_max_size');
                $upload_mb = min($max_upload, $max_post);
                $this->errors[] = sprintf(
                    $this->l(
                        'The File %1$s exceeds the size allowed by the server. The limit is set to %2$d MB.'
                    ),
                    '<b>' . $_FILES['attachment_file']['name'] . '  ',
                    '<b>' . $upload_mb . ' '
                );
            } else {
                $this->errors[] = $this->l('File is missing');
            }

            if (empty($this->errors) && isset($uniqid)) {
                $attachment = new Attachment();
                foreach ($languages as $language) {
                    if (Tools::getIsset('attachment_name_' . (int) $language['id_lang'])) {
                        $attachment->name[(int) $language['id_lang']] = Tools::getValue('attachment_name_' .
                            (int) $language['id_lang']);
                    }
                    if (Tools::getIsset('attachment_description_' . (int) $language['id_lang'])) {
                        $attachment->description[(int) $language['id_lang']] = Tools::getValue(
                            'attachment_description_' . (int) $language['id_lang']
                        );
                    }
                }
                $attachment->file = $uniqid;
                $attachment->mime = $_FILES['attachment_file']['type'];
                $attachment->file_name = $_FILES['attachment_file']['name'];
                if (empty($attachment->mime) || Tools::strlen($attachment->mime) > 128) {
                    $this->errors[] = $this->l('Invalid file extension');
                }
                if (!Validate::isGenericName($attachment->file_name)) {
                    $this->errors[] = $this->l('Invalid file name');
                }
                if (Tools::strlen($attachment->file_name) > 128) {
                    $this->errors[] = $this->l('File name too long');
                }
                if (empty($this->errors)) {
                    $res = $attachment->add();
                    if (!$res) {
                        $this->errors[] = $this->l('Unable to add this attachment in the database');
                    } else {
                        // Add association with attachemnt and seller
                        $sellerinfoAttachment = new SellerinfoAttachment();
                        $sellerinfoAttachment->setSellerinfo($this->sellerinfo)->setIdAttachment($attachment->id);
                        $this->entityManager->persist($sellerinfoAttachment);
                        $this->entityManager->flush();

                        $id_product = (int) Tools::getValue($this->identifier);
                        $res = $attachment->attachProduct($id_product);
                        if (!$res) {
                            $this->errors[] = $this->l('Unable to associate this attachment to product');
                        }
                    }
                } else {
                    $this->errors[] = $this->l('Invalid file');
                }
            }
        }
    }

    public function processSubmitAttachments()
    {
        if ($id = (int) Tools::getValue($this->identifier)) {
            $attachments = Tools::getValue('arrayAttachments');
            if (empty($attachments)) {
                $this->object->cache_has_attachments = false;
                $this->object->save();
            }

            if (!Attachment::attachToProduct($id, $attachments)) {
                $this->errors[] = $this->l('There was an error while saving product attachments.');
            } else {
                $this->object->cache_has_attachments = true;
                $this->object->save();
            }
        }
    }

    public function processSubmitDescription()
    {
        $validateFields = ['description_short', 'description', 'meta_description', 'meta_title', 'link_rewrite', 'tags'];

        foreach (Language::getLanguages(true) as $language) {
            if (empty(Tools::getValue('link_rewrite_' . $language['id_lang']))) {
                $this->object->link_rewrite[$language['id_lang']] = Tools::link_rewrite($this->object->name[$language['id_lang']]);
            }
        }

        $this->copyFromPost($this->object, $this->table);

        $limit = (int) Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT');

        if ($limit <= 0) {
            $limit = 800;
        }

        if (Tools::strlen($this->object->description_short[$this->id_language]) > $limit) {
            $this->errors[] = $this->trans('Short description is too long', [], 'Modules.Agilemultisellerpro.Product');
            return;
        }

        foreach ($this->validateRules(false, false) as $error) {
            if (in_array($error['field'], $validateFields)) {
                $this->errors[] = $error['msg'];
            }
        }

        if (count($this->errors) > 0) {
            return;
        }

        if (method_exists($this->object, 'update') && !$this->object->update()) {
            $this->errors[] = $this->tras('An error occurred while updating object.', [], 'Modules.Agilemultisellerpro.Product') .
                ' ' . $this->table . ' (' . Db::getInstance()->getMsgError() . ') ';
        }

        $this->updateTags(Language::getLanguages(false), $this->object);
    }

    public function processSubmitOptions()
    {
        $validateFields = ['ean13', 'upc', 'visibility', 'available_for_order', 'show_price', 'online_only', 'condition'];

        $this->copyFromPost($this->object, $this->table);

        $this->object->online_only = (int) Tools::getValue('online_only');
        $this->object->available_for_order = (int) Tools::getValue('available_for_order');
        $this->object->show_price = (int) Tools::getValue('show_price');

        if ($this->object->available_for_order) {
            $this->object->show_price = 1;
        }

        foreach ($this->validateRules(false, false) as $error) {
            if (in_array($error['field'], $validateFields)) {
                $this->errors[] = $error['msg'];
            }
        }

        if (count($this->errors) > 0) {
            return;
        }

        if (method_exists($this->object, 'update') && !$this->object->update()) {
            $this->errors[] = $this->tras('An error occurred while updating object.', [], 'Modules.Agilemultisellerpro.Product') .
                ' ' . $this->table . ' (' . Db::getInstance()->getMsgError() . ') ';
            return;
        }
    }

    private function getSellerinfoMembershipType()
    {
        $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);

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