<?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
 */
namespace PrestaShop\Module\AgileMultisellerPro\Helper;

use PrestaShop\Module\AgileMultisellerPro\Form\Configuration\DataConfiguration;
use PrestaShop\Module\AgileMultisellerPro\Repository\SellerinfoCommissionRepository;
use PrestaShop\PrestaShop\Adapter\ContainerBuilder;

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

class AgileHelper
{
    public static $countSellerInfo = false;

    public static function buildContainer()
    {
        return ContainerBuilder::getContainer('front', _PS_MODE_DEV_);
    }

    private static function getPathFromName($cateinfo, $for_id, $path)
    {
        if ($for_id == 1) {
            return '/' . $path;
        }
        if (!isset($cateinfo[$for_id])) {
            return $path;
        }
        if (!empty($path)) {
            $path = '/' . $path;
        }
        $path = $cateinfo[$for_id]['name'] . $path;
        if ($cateinfo[$for_id]['id_parent'] > 0) {
            $path = self::getPathFromName($cateinfo, $cateinfo[$for_id]['id_parent'], $path);
        }
        return $path;
    }

    public static function getSortedFullnameCategory($caterows, $isSymfonyForm = false)
    {
        $nameIndex = [];
        if (!empty($caterows)) {
            foreach ($caterows as $cate) {
                $nameIndex[$cate['id_category']] = $cate;
            }
        }

        $fullnameIndex = [];

        foreach ($caterows as $caterow) {
            $fullnameIndex[$caterow['id_category']] = self::getPathFromName($nameIndex, $caterow['id_category'], '');
        }

        unset($nameIndex);

        asort($fullnameIndex);
        $categories = [];
        $root = \Category::getRootCategory();
        $rootfullname = isset($fullnameIndex[$root->id]) ? $fullnameIndex[$root->id] : '';
        $rootfullnamelen = strlen($rootfullname);
        foreach ($fullnameIndex as $id => $name) {
            if (strlen($name) >= $rootfullnamelen && substr($name, 0, $rootfullnamelen) == $rootfullname) {
                if (true === $isSymfonyForm) {
                    $categories[$name] = $id;
                } else {
                    $categories[] = ['id_category' => $id, 'name' => $name];
                }
            }
        }
        unset($fullnameIndex);

        return $categories;
    }

    public static function getImageDirectory($idSellerinfo = 0, $fileName = null): string
    {
        $path = _PS_ROOT_DIR_ . AgileConst::LOGO_FOLDER;

        if ($idSellerinfo) {
            $path .= $idSellerinfo . DIRECTORY_SEPARATOR;
        }

        if ($fileName) {
            $path .= $fileName . '.jpg';
        }

        return $path;
    }

    public static function checkImage($idSellerinfo, $fileName): bool
    {
        return file_exists(self::getImageDirectory($idSellerinfo, $fileName));
    }

    public static function getImagePath($idSellerinfo, $fileName): ?string
    {
        $path = AgileConst::LOGO_FOLDER . $idSellerinfo . DIRECTORY_SEPARATOR . $fileName . '.jpg';

        if (!file_exists(_PS_ROOT_DIR_ . $path)) {
            return null;
        }

        return $path . '?v=' . self::getImageDateUpdate($idSellerinfo, $fileName);
    }

    public static function getImageDateUpdate($idSellerinfo, $fileName): int
    {
        $dateUpd = 0;
        $imageDirectory = self::getImageDirectory($idSellerinfo, $fileName);

        if (file_exists($imageDirectory)) {
            $dateUpd = filemtime($imageDirectory);
        }

        return (int) $dateUpd;
    }

    public static function getCustomFields()
    {
        $custom_fields = [];
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_TEXT_QUANTITY; ++$i) {
            $custom_fields[] = 'AGILE_MS_SELLER_TEXT' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_HTML_QUANTITY; ++$i) {
            $custom_fields[] = 'AGILE_MS_SELLER_HTML' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_NUMBER_QUANTITY; ++$i) {
            $custom_fields[] = 'AGILE_MS_SELLER_NUMBER' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_DATE_QUANTITY; ++$i) {
            $custom_fields[] = 'AGILE_MS_SELLER_DATE' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_STRING_QUANTITY; ++$i) {
            $custom_fields[] = 'AGILE_MS_SELLER_STRING' . $i;
        }
        return $custom_fields;
    }

    public static function getCustomLabels($surfix = '')
    {
        $customLabels = [];
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_TEXT_QUANTITY; ++$i) {
            // $customLabels[] = $this->l('Text1') . $surfix;
            $customLabels['ams_custom_text' . $i] = 'Text' . $i . $surfix;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_HTML_QUANTITY; ++$i) {
            $customLabels['ams_custom_html' . $i] = 'Html' . $i . $surfix;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_NUMBER_QUANTITY; ++$i) {
            $customLabels['ams_custom_number' . $i] = 'Number' . $i . $surfix;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_DATE_QUANTITY; ++$i) {
            $customLabels['ams_custom_date' . $i] = 'Date' . $i . $surfix;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_STRING_QUANTITY; ++$i) {
            $customLabels['ams_custom_string' . $i] = 'String' . $i . $surfix;
        }

        return $customLabels;
    }

    public static function getCustomHints()
    {
        $customHints = [];
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_TEXT_QUANTITY; ++$i) {
            // $customLabels[] = $this->l('Text1') . $surfix;
            $customHints['ams_custom_text' . $i] = 'Hints for Text' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_HTML_QUANTITY; ++$i) {
            $customHints['ams_custom_html' . $i] = 'Hints for Html' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_NUMBER_QUANTITY; ++$i) {
            $customHints['ams_custom_number' . $i] = 'Hints for Number' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_DATE_QUANTITY; ++$i) {
            $customHints['ams_custom_date' . $i] = 'Hints for Date' . $i;
        }
        for ($i = 1; $i <= DataConfiguration::AGILE_MS_SELLER_STRING_QUANTITY; ++$i) {
            $customHints['ams_custom_string' . $i] = 'Hints for String' . $i;
        }

        return $customHints;
    }

    public static function getAjaxUrls()
    {
        $context = \Context::getContext();

        return [
            'ajax_agile_categories' => $context->link->getModuleLink('agilemultisellerpro', 'ajaxagilecategories'),
            'ajax_agile_getcustomers' => $context->link->getModuleLink('agilemultisellerpro', 'ajaxagilegetcustomers'),
            'ajax_products' => $context->link->getModuleLink('agilemultisellerpro', 'ajaxproducts'),
            'ajax_products_list' => $context->link->getModuleLink('agilemultisellerpro', 'ajaxproductslist'),
            'agile_ajax_url' => $context->link->getModuleLink('agilemultisellerpro', 'ajax'),
        ];
    }

    public static function hookGenerateCSV($data)
    {
        if (empty($data['text_delimiter'])) {
            $data['text_delimiter'] = ';';
        }

        $handler = fopen('php://output', 'w');

        fputcsv($handler, $data['export_headers'], $data['text_delimiter']);
        foreach ($data['export_content'] as $line) {
            fputcsv($handler, $line, $data['text_delimiter']);
        }

        exit;
    }

    public static function retrieveColumnValues($dataset, $column, $includeempty = true)
    {
        if (empty($column) || empty($dataset) || !is_array($dataset)) {
            return [];
        }
        $results = [];
        foreach ($dataset as $datarow) {
            if (!isset($datarow[$column])) {
                continue;
            }
            if (!$includeempty && empty($datarow[$column])) {
                continue;
            }
            $results[] = $datarow[$column];
        }
        return $results;
    }

    public static function getSellerUrlByShopId($idShop, $idLang = null)
    {
        $shop = new \Shop($idShop);

        if (isset($shop->virtual_uri) && trim($shop->virtual_uri, ' /')) {
            $virtualUri = ltrim($shop->virtual_uri, '/');

            $linkSeller = (new \Link())->getModuleLink(
                'agilemultisellerpro', // Module name
                'seller', // Controller name
                ['shop_virtual_url' => $virtualUri],
                null,
                $idLang,
            );
        } else {
            $linkSeller = '#';
        }

        return $linkSeller;
    }

    public static function createNewShop($id_seller, $name)
    {
        if (empty($name)) {
            $name = 'shop';
        }

        if (\Shop::getIdByName($name)) {
            $name = $name . '-' . $id_seller;
        }

        $defshop = new \Shop((int) \Configuration::get('PS_SHOP_DEFAULT'));

        $shop = new \Shop();
        $shop->name = $name;
        $shop->id_shop_group = $defshop->id_shop_group;
        $shop->id_category = $defshop->id_category;
        $shop->active = 1;
        $shop->deleted = 0;
        $shop->theme_name = $defshop->theme_name;
        $shop->add();

        $defShopUrl = \ShopUrl::getShopUrls($defshop->id)[0];

        $shopurl = new \ShopUrl($defShopUrl->id);
        $shopurl->id = 0;
        $shopurl->id_shop = $shop->id;
        $shopurl->virtual_uri = \Tools::link_rewrite($name);

        $id_found = $shopurl->canAddThisUrl(
            $shopurl->domain,
            $shopurl->domain_ssl,
            $shopurl->physical_uri,
            $shopurl->virtual_uri
        );

        if ((int) $id_found > 0) {
            $shopurl->virtual_uri = $shopurl->virtual_uri . '-' . $id_seller;
        }
        $shopurl->active = 1;
        $shopurl->add();

        return $shop;
    }

    public static function getZoneID($id_address_delivery, $id_customer)
    {
        if (isset($id_address_delivery)
            && $id_address_delivery
            && \Customer::customerHasAddress($id_customer, $id_address_delivery)
        ) {
            $id_zone = \Address::getZoneById((int) $id_address_delivery);
        } else {
            $defaultCountry = new \Country(
                \Configuration::get('PS_COUNTRY_DEFAULT'),
                \Configuration::get('PS_LANG_DEFAULT')
            );
            $id_zone = (int) $defaultCountry->id_zone;
        }
        return $id_zone;
    }

    public static function getComissionTypes($isFlip = false, $isNoneType = true)
    {
        $translator = \Context::getContext()->getTranslator();

        $types = [];

        if (true === $isNoneType) {
            $types[0] = '---';
        }

        $types[SellerinfoCommissionRepository::SELLER_PAID_TO_STORE] = $translator->trans('Seller paid to store', [], 'Modules.Agilemultisellerpro.Comission');
        $types[SellerinfoCommissionRepository::STORE_PAID_TO_SELLER] = $translator->trans('Store paid to seller', [], 'Modules.Agilemultisellerpro.Comission');
        $types[SellerinfoCommissionRepository::RECORD_TYPE_BUYER_PAY_STORE] = $translator->trans('Customer paid to store', [], 'Modules.Agilemultisellerpro.Comission');
        $types[SellerinfoCommissionRepository::RECORD_TYPE_BUYER_PAY_SELLER] = $translator->trans('Customer paid to seller', [], 'Modules.Agilemultisellerpro.Comission');
        $types[SellerinfoCommissionRepository::RECORD_TYPE_BUYER_PAY_BOTH] = $translator->trans('Customer paid to both seller and store', [], 'Modules.Agilemultisellerpro.Comission');
        $types[SellerinfoCommissionRepository::RECORD_TYPE_ORDER_CANCELLATION] = $translator->trans('Order Cancellation', [], 'Modules.Agilemultisellerpro.Comission');

        if (true === $isFlip) {
            $types = array_flip($types);
        }

        return $types;
    }

    public static function getComissionTypeNameByType($recordTtype)
    {
        $typeName = '---';

        $comissionTypes = self::getComissionTypes(false, false);

        if (isset($comissionTypes[$recordTtype])) {
            $typeName = $comissionTypes[$recordTtype];
        }

        return $typeName;
    }

    public static function getCommissionCreationDefaultStatuses()
    {
        return _PS_OS_PAYMENT_ . ',' . _PS_OS_WS_PAYMENT_ . ',' . _PS_OS_SHIPPING_ . ',' . _PS_OS_DELIVERED_;
    }

    public static function getCommissionCancellationDefaultStatuses()
    {
        return _PS_OS_CANCELED_ . ',' . _PS_OS_REFUND_;
    }

    public static function stringIDsToArray($ids)
    {
        if (empty($ids)) {
            return [];
        }

        return explode(',', $ids);
    }

    public static function getCarrierTax($carrier, $idCart, $use_tax = true)
    {
        if ($use_tax == false) {
            return 0;
        }

        $cart = new \Cart($idCart);

        if (\Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_invoice') {
            $address_id = (int) $cart->id_address_invoice;
        } elseif ($cart->id_address_delivery) {
            $address_id = (int) $cart->id_address_delivery;
        } else {
            $address_id = null;
        }
        if (!\Address::addressExists($address_id, true)) {
            $address_id = null;
        }
        if ($use_tax && !\Tax::excludeTaxeOption()) {
            $address = \Address::initialize((int) $address_id);
            if (\Configuration::get('PS_ATCP_SHIPWRAP')) {
                $carrier_tax = 0;
            } else {
                $carrier_tax = $carrier->getTaxesRate($address);
            }
        }
        return $carrier_tax;
    }

    public static function createCategoryByName($name)
    {
        $category = new \Category();
        $languages = \Language::getLanguages(false);
        foreach ($languages as $lang) {
            $category->name[$lang['id_lang']] = $name;
            $category->link_rewrite[$lang['id_lang']] = \Tools::link_rewrite($name);
        }

        $category->id_parent = \Configuration::get('PS_HOME_CATEGORY');
        $category->id_shop_default = 1;
        $category->level = 2;
        $category->is_root_category = 0;
        $category->position = 0;
        $category->active = 1;
        $category->save();

        return $category;
    }

    public static function addCategoryImage($id_category, $url)
    {
        return AgileHelper::copyImg($id_category, null, $url, $entity = 'categories', true);
    }

    public static function copyImg($id_entity, $id_image, $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;
        }
        $url = str_replace(' ', '%20', trim($url));

        if (!\ImageManager::checkImageMemoryLimit($url)) {
            return false;
        }

        if (AgileHelper::copy($url, $tmpfile)) {
            \ImageManager::resize($tmpfile, $path . '.jpg');
            $images_types = \ImageType::getImagesTypes($entity);

            if ($regenerate) {
                foreach ($images_types as $image_type) {
                    \ImageManager::resize($tmpfile, $path . '-' . stripslashes($image_type['name']) . '.jpg', $image_type['width'], $image_type['height']);
                    if (in_array($image_type['id_image_type'], $watermark_types)) {
                        Hook::exec('actionWatermark', ['id_image' => $id_image, 'id_product' => $id_entity]);
                    }
                }
            }
        } else {
            unlink($tmpfile);
            return false;
        }
        unlink($tmpfile);
        return true;
    }

    public static function copy($source, $destination, $stream_context = null)
    {
        return \Tools::copy($source, $destination, $stream_context);
    }

    public static function createProductWithBasics($id_category, $name, $price, $is_virtual = true, $active = true)
    {
        $product = new \Product();
        $languages = \Language::getLanguages(false);
        foreach ($languages as $lang) {
            $product->name[$lang['id_lang']] = $name;
            $product->link_rewrite[$lang['id_lang']] = \Tools::link_rewrite($name);
        }

        $product->id_category_default = (int) $id_category;
        $product->id_shop_default = 1;
        $product->wholesale_price = $price;
        $product->price = $price;
        $product->ecotax = 0;
        $product->available_for_order = 1;
        $product->visibility = 'both';
        $product->is_virtual = $is_virtual;
        $product->id_tax_rules_group = 0;

        $product->active = $active;
        $product->save();
        $product->addStockMvt(2147483647, 1);

        AgileHelper::setDefaultCategory($product, $id_category);

        return $product;
    }

    public static function setDefaultCategory($product, $id_category)
    {
        if (!\Validate::isLoadedObject($product)) {
            return;
        }

        $product->id_category_default = $id_category;
        $sql = 'DELETE FROM ' . _DB_PREFIX_ . 'category_product WHERE id_category=' . (int) $id_category . ' AND id_product=' . (int) $product->id;
        \Db::getinstance()->execute($sql);
        $sql = 'INSERT INTO ' . _DB_PREFIX_ . 'category_product (id_category, id_product, position) VALUES (' . (int) $id_category . ',' . (int) $product->id . ',0)';
        \Db::getinstance()->execute($sql);
        $product->save();
    }

    public static function addProductImage($id_product, $url)
    {
        $url = trim($url);
        if (empty($url)) {
            return false;
        }

        $url = str_replace(' ', '%20', $url);
        $product_has_images = (bool) \Image::getImages(\Context::getContext()->language->id, (int) $id_product);

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

        if (
            $image->validateFields(false, true) === true
            && $image->validateFieldsLang(false, true) === true
            && $image->add()
        ) {
            $image->associateTo([1]);
            return AgileHelper::copyImg($id_product, $image->id, $url, 'products', !\Tools::getValue('regenerate'));
        }
        return false;
    }

    public static function getOrderIdFromMaildata($templateVars)
    {
        $order_name = $templateVars['{order_name}'];
        $idx = 0;
        $oninfo = explode('#', $order_name);

        if (count($oninfo) > 1) {
            $order_name = $oninfo[0];
            $idx = (int) $oninfo[1] - 1;
        }

        $orders = \Db::getInstance()->executeS('SELECT id_order FROM ' . _DB_PREFIX_ . 'orders WHERE reference=\'' . pSQL($order_name) . '\' ORDER BY id_order');

        $id_order = (int) $orders[$idx]['id_order'];

        if ($id_order <= 0) {
            $id_order = (int) str_replace('#', '', $templateVars['{order_name}']);
        }

        if ($id_order <= 0) {
            $id_order = (int) $templateVars['{id_order}'];
        }

        return $id_order;
    }

    public static function getTokenByType($type)
    {
        $key = 'agilemultisellerpro';

        switch ($type) {
            case 'hideproducts':
                $key .= 'hideproducts';
                break;
            default:
                $key .= \Tools::getShopDomain();
                break;
        }

        return md5($key);
    }

    public static function getServerParams()
    {
        $curl = curl_version();
        $serverParams = [
            'max_time' => [
                'name' => 'Max time',
                'value' => ini_get('max_execution_time'),
            ],
            'curl' => [
                'name' => 'Curl',
                'value' => !empty($curl['version']) ? 'Enabled' : 'Disabled',
            ],
            'php_version' => [
                'name' => 'PHP Version',
                'value' => phpversion(),
            ],
        ];

        return $serverParams;
    }

    /**
     * @return bool
     */
    public static function isShopVersion8()
    {
        return version_compare(_PS_VERSION_, '8.0.0', '>=');
    }

    /**
     * Get hearder Authorization
     * */
    public static function getAuthorizationHeader()
    {
        $headers = null;
        if (isset($_SERVER['Authorization'])) {
            $headers = trim($_SERVER['Authorization']);
        } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or fast CGI
            $headers = trim($_SERVER['HTTP_AUTHORIZATION']);
        } elseif (function_exists('apache_request_headers')) {
            $requestHeaders = apache_request_headers();
            // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
            $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
            if (isset($requestHeaders['Authorization'])) {
                $headers = trim($requestHeaders['Authorization']);
            }
        }
        return $headers;
    }

    /**
     * get access token from header
     * */
    public static function getBearerToken()
    {
        $headers = self::getAuthorizationHeader();

        // HEADER: Get the access token from the header
        if (!empty($headers)) {
            if (preg_match('/(Bearer|Basic)\s(\S+)/', $headers, $matches)) {
                return $matches[2];
            }
        }
        return null;
    }
}
