<?php

namespace system\library\marketplace;

use system\entity\filter\baseFilter;

class MktPriceAdjustments
{
    private $config;
    private $db;
    private $language;
    private $request;
    private $load;
    private $registry;
    private $settings;
    private $validate;

    public function __construct($registry, $settings = [])
    {
        $this->registry = $registry;
        $this->config = $registry->get('config');
        $this->db = $registry->get('db');
        $this->language = $registry->get('language');
        $this->request = $registry->get('request');
        $this->load = $registry->get('load');
        $this->validate = $registry->get('validate');

        if (!isset($settings['tipo_integracao'])) {
            throw new \Exception('Tipo de integração não informado ao criar a classe MktPriceAdjustments');
        }

        $this->settings = $settings;

        $this->load->language('marketplace/marketprice');

        $this->load->dmodel('marketplace/mktprice');
        $this->load->dmodel('marketplace/mktadjustment');
        $this->load->dmodel('sale/customer_group');

        $this->load->type('tipocomum');
        $this->load->type('tipomercadolivre');

        $this->load->helper('ftr_geral');
    }

    public function __get($name)
    {
        return $this->registry->get($name);
    }

    /**
     * @return string
     */
    public function getDataJson(): string
    {
        $data = $this->load->language('marketplace/marketprice', null, false);

        $data['TypesForJs'] = array(
            \Type_MarketplaceTypeAdjustment::getTypeForJs(),
            \Type_MarketplaceAdjustmentPrice::getTypeForJs(),
        );

        $data['Type_MlSettings'] = \Type_MlSettings::getEnumList();
        $data['Type_MarketplaceAdjustmentPrice'] = \Type_MarketplaceAdjustmentPrice::getEnumList();
        $data['tipo_integracao'] = $this->settings['tipo_integracao'];

        switch ($data['tipo_integracao']) {
            case \Type_MarketPlace::Tp_Mercadolivre:
                $data['entry_marketprice_price_standard_obs'] = sprintf($data['entry_marketprice_price_standard_obs'], 'no MercadoLivre');
                break;

            case \Type_MarketPlace::Tp_SkyHub:
                $data['entry_marketprice_price_standard_obs'] = sprintf($data['entry_marketprice_price_standard_obs'], 'no SkyHub');
                break;

            case \Type_MarketPlace::Tp_Galeriapage:
                $data['entry_marketprice_price_standard_obs'] = sprintf($data['entry_marketprice_price_standard_obs'], 'na GaleriaPage');
                break;
            case \Type_MarketPlace::Tp_Shopee:
                $data['entry_marketprice_price_standard_obs'] = sprintf($data['entry_marketprice_price_standard_obs'], 'na Shopee');
                break;

            default: $data['entry_marketprice_price_standard_obs'] = sprintf($data['entry_marketprice_price_standard_obs'], '');
        }

        $customer_groups = array();
        $results = $this->dmodel_sale_customer_group->getCustomerGroups();
        foreach ($results as $key => $customer_group) {
            $customer_groups[] = array(
                'customer_group_id' => $customer_group['customer_group_id'],
                'name' => $customer_group['name']
            );
        }
        $data['customer_groups'] = $customer_groups;

        $data['mktpriceadjustments'] = $this->dmodel_marketplace_mktprice->getMktPriceAdjustments($this->settings['tipo_integracao']);

        return \json_encode($data);
    }

    /**
     * Valida as informações para salvar na base da MktPriceAdjustments
     *
     * @throws \Exception
     */
    public function validate()
    {
        $this->load->helper('ftr_geral');
        $this->load->helper('ftr_validacao');

        extract($this->request->post);

        $errors = [];

        if (isset($mktpriceadjustments['data'])) {

            foreach ($mktpriceadjustments['data'] as $keyPrices => $prices) {
                $mktpriceadjustments_error = $this->validate->execute([
                    'mktPrice[' . $keyPrices . '][customer_group_id]' => [
                        'value' => $prices['customer_group_id'],
                        'validates' => ['isEmpty'],
                    ],
                    'mktPrice[' . $keyPrices . '][standard]' => [
                        'value' => $prices['standard'],
                        'validates' => [
                            [
                                'method' => 'targetIsMandatory',
                                'field' => 'standard',
                                'message' => 'É obrigátorio escolher uma tabela padrão',
                                'compare' => $mktpriceadjustments['data']
                            ]
                        ],
                    ]
                ]);

                if (count($mktpriceadjustments_error) > 0) {
                    $errors = array_merge($errors, $mktpriceadjustments_error);
                }

                $targetIsDuplicatedObject = false ;
                if (isset($prices['marketplace_price_adjustments'])) {
                    foreach ($prices['marketplace_price_adjustments'] as $keyAdjustments => $adjustment) {
                        $marketplace_price_adjustments_error = $this->validate->execute([
                            'mktPrice[' . $keyPrices . '][marketplace_price_adjustments][' . $keyAdjustments . '][value]' => [
                                'value' => $adjustment['value'],
                                'validates' => [
                                    'isEmpty',
                                    [
                                        'method' => 'isMinMaxNumber',
                                        'min' => 0,
                                        'max' => 99,
                                        'condition' => ($prices['marketplace_price_adjustments'][$keyAdjustments]['adjustment'] == \Type_MarketplaceAdjustmentPrice::Tp_Percentual
                                        && $prices['marketplace_price_adjustments'][$keyAdjustments]['type_adjustment'] == \Type_MarketplaceTypeAdjustment::Tp_Decre)
                                    ],
                                ],
                            ]
                        ]);

                        if (count($marketplace_price_adjustments_error) > 0) {
                            $errors = array_merge($errors, $marketplace_price_adjustments_error);
                        }
                    }

                    $targetIsDuplicatedObject = $this->validate->targetIsDuplicatedObject(
                        $prices['marketplace_price_adjustments'],
                        'Não pode haver configurações repetidas nos ajustes de preços!',
                        ['type_adjustment','adjustment']
                    );
                }

                if ($targetIsDuplicatedObject) {
                    $errors['warning'] = $targetIsDuplicatedObject;
                }
            }

        } else {
            $errors['warning'] = $this->language->get('error_marketprice_not_exist');
        }

        return $errors;
    }

    /**
     * Salva as informações referente a preço dos marketplaces
     *
     * @throws \Exception
     */
    public function save()
    {
        try {

            extract($this->request->post);

            $this->db->startTransaction();

            if ($mktpriceadjustments) {

                $this->load->dmodel('marketplace/mktprice');

                /**
                 * inseri / edita os valores de mktPrice que foram alterados/inseridos pela interface
                 */
                foreach ($mktpriceadjustments['data'] as $keyMkt => $mktPrices) {

                    $this->dmodel_marketplace_mktprice->getNewEntityClass();
                    foreach ($mktPrices as $keyPrice => $price) {
                        if (($price != '') && (!is_array($price))) {
                            $this->dmodel_marketplace_mktprice->setClassValues($keyPrice, $price);
                        }
                    }

                    $marketplacePrice = $this->dmodel_marketplace_mktprice->getEntityClass();
                    if ($marketplacePrice->getMarketplacePriceId() != null) {
                        $marketplacePrice = $this->dmodel_marketplace_mktprice->update();
                    } else {
                        $marketplacePrice = $this->dmodel_marketplace_mktprice->insert();
                    }

                    $arrayAdjustmentsMd5 = [];

                    $baseFilter = new BaseFilter();
                    $baseFilter->setWhere(
                        'marketplace_price_id',
                        \Type_OperationsComparation::Equals,
                        $marketplacePrice->getMarketplacePriceId()
                    );
                    $this->dmodel_marketplace_mktadjustment->delete($baseFilter);

                    if (isset($mktPrices['marketplace_price_adjustments']) && count($mktPrices['marketplace_price_adjustments']) > 0) {

                        foreach ($mktPrices['marketplace_price_adjustments'] as $keyPrice => $adjustments) {

                            $this->dmodel_marketplace_mktadjustment->getNewEntityClass();

                            foreach ($adjustments as $keyAdjustment => $adjustment) {
                                if (($adjustment != '') && !is_array($adjustment)) {
                                    $this->dmodel_marketplace_mktadjustment->setClassValues($keyAdjustment, $adjustment);
                                }
                            }

                            $priceAdjustments = $this->dmodel_marketplace_mktadjustment->getEntityClass();
                            $priceAdjustments->setMarketplacePriceId($marketplacePrice->getMarketplacePriceId());
                            $priceAdjustments = $this->dmodel_marketplace_mktadjustment->insert();
                            $arrayAdjustmentsMd5[] = $priceAdjustments->getMarketplaceAdjustmentMd5Array();

                        }

                    }

                    $arrayPridMd5 = [
                        $marketplacePrice->getMarketplacePriceMd5Array(),
                        $arrayAdjustmentsMd5
                    ];
                    $marketplacePrice->setMarketplacePriceMd5(\md5(\json_encode($arrayPridMd5)));
                    $this->dmodel_marketplace_mktprice->update();
                }

                /**
                 * deleta os valores da mktprice que foram removidos pela interface
                 */
                if (isset($mktpriceadjustments['delete']) && (count(array_filter($mktpriceadjustments['delete'])) > 0)) {
                    foreach ($mktpriceadjustments['delete'] as $keyMkt => $mktPricesId) {
                        $baseFilter = new BaseFilter();
                        $baseFilter->setWhere(
                            'marketplace_price_id',
                            \Type_OperationsComparation::Equals,
                            $mktPricesId
                        );
                        $this->dmodel_marketplace_mktprice->delete($baseFilter);
                    }
                }

            }

            $this->db->commit();

            unset($this->request->post['mktpriceadjustments']);

            return $this->dmodel_marketplace_mktprice->getMktPriceAdjustments($this->settings['tipo_integracao']);

        } catch (\Exception $e) {
            $this->db->rollback();
            throw $e;
        }
    }

    public function computedPriceAdjustment($value, $marketplace_price_id)
    {
        $baseFilter = new BaseFilter();
        $baseFilter->setWhere(
            'marketplace_price_id',
            \Type_OperationsComparation::Equals,
            $marketplace_price_id
        );

        $adjustments = $this->dmodel_marketplace_mktadjustment->findBy($baseFilter);

        return $this->calculateAdjustmenst($adjustments, $value, true);
    }

    public function computedAdjustmentTotal($value, $marketplace_price_id)
    {
        $baseFilter = new BaseFilter();
        $baseFilter->setWhere(
            'marketplace_price_id',
            \Type_OperationsComparation::Equals,
            $marketplace_price_id
        );

        $adjustments = $this->dmodel_marketplace_mktadjustment->findBy($baseFilter);

        return $this->calculateAdjustmenst($adjustments, $value);
    }

    public function getMktPrice(array $productInfo = [])
    {
        $mkt_price = $productInfo['price'];

        if (!isset($productInfo['marketplace_price_id']) || is_null($productInfo['marketplace_price_id'])) {
            $result = $this->dmodel_marketplace_mktprice->getStandardMktPrice($this->settings['tipo_integracao']);
        } else {
            $result = $this->dmodel_marketplace_mktprice->find($productInfo['marketplace_price_id']);
        }

        if ($result) {
            $pdDisc = $this->db->query('SELECT price FROM oc_product_discount WHERE product_id = ' . $productInfo['product_id'] . ' and customer_group_id= ' . $result->getCustomerGroupId())->row;
            if (isset($pdDisc['price'])) {
                $mkt_price = $pdDisc['price'];
            }

            $mkt_price = $this->computedPriceAdjustment($mkt_price, $result->getMarketplacePriceId());
        }

        return $mkt_price;
    }

    private function calculateAdjustmenst($adjustments, $value, bool $total = false)
    {
        $ajustmentValue = 0;

        if ($adjustments) {
            foreach ($adjustments as $adjustment) {
                if ($adjustment->getAdjustment() == \Type_MarketplaceAdjustmentPrice::Tp_Percentual) {

                    if ($adjustment->getTypeAdjustment() == \Type_MarketplaceTypeAdjustment::Tp_Acre) {
                        $ajustmentValue += (($value * $adjustment->getValue()) / 100);
                    } else {
                        $ajustmentValue += ((($value * $adjustment->getValue()) / 100) * -1);
                    }

                } else {

                    if ($adjustment->getTypeAdjustment() == \Type_MarketplaceTypeAdjustment::Tp_Acre) {
                        $ajustmentValue += $adjustment->getValue();
                    } else {
                        $ajustmentValue -= $adjustment->getValue();
                    }

                }
            }
        }

        if (!$total) {
            return $ajustmentValue;
        }

        $value += $ajustmentValue;
        return $value;
    }

}