<?php

final class SkyHub extends SkyHubUtils
{

    public function setAtualizarEstoqueFromProdutos(MktProduto $produto, $produtoRetorno)
    {

        $jsonSend = array();
        if ($produto->hasVariations()) {
            $addedVars = false;
            /*Funciona atualizar todas as variações de uma vez mandando PUT no prodto(Pelo menos "quando eu fiz funcionava"),
            porém o skyhub pede que atualize as variações uma por uma na homologação, dando put na variations*/
            foreach ($produto->getVariacao() as $variacao) {
                $jsonSend = array();
                $jsonSend['variation'] = array(
                    'qty' => $variacao->getQuantity()
                );
                $jsonSend['variation']['specifications'][] = array(
                    "key" => "price",
                    "value" => $variacao->getValor()
                );

                $varMktId = ($variacao->getMktVariation_id() != null) ? $variacao->getMktVariation_id() : 'P' . $variacao->getProductid();
                $this->updateVariation($varMktId, json_encode($jsonSend));
            }
        }

        //Envia o produto principal por ultimo
        $jsonSend['product'] = array(
            'qty' => $produto->getQuantity(),
            'price' => $produto->getPrice()
        );

        if ($produto->hasVariations()) {
            $mktID = ($produto->getMktId() != null) ? $produto->getMktId() : 'G' . $produto->getProductid();
        } else {
            $mktID = ($produto->getMktId() != null) ? $produto->getMktId() : 'P' . $produto->getProductid();
        }

        $retorno = $this->updateProduct($mktID, json_encode($jsonSend));

        if ($this->httpcode == TypeSkyHubHttpCode::Tp_NaoEncontrado) {
            throw new ExceptionProductNotExists('Não foi possível encontrar Product: ' . $produto->getMktId());
        } else {
            if ($retorno) {
                $produto->setMktRetorno($produtoRetorno);
                return $produto;
            } else {
                throw new exception($this->error);
            }
        }

    }

    public function setAtualizarEstoque(MktProduto $produto, $mkt_product_id)
    {
        $produtoRetorno = $this->getProduto($mkt_product_id);
        return $this->setAtualizarEstoqueFromProdutos($produto, $produtoRetorno);
    }


    public function getProduto($mktplace_id, $mkt_produto = null)
    {
        $prodwbs = $this->getProduct($mktplace_id);

        if ($prodwbs) {
            //$prodwbs = $retorno;//->products[0]; //testar se volta array em alguma situ. pq antes voltava...
            $produto = new MktProdutoRetorno();
            $produto->setmktIntegrationId($prodwbs->sku);
            $produto->setmktName($prodwbs->name);
            $produto->setmktLink('');
            $produto->setmktTipo(Type_MarketPlace::Tp_SkyHub);
            $produto->setmktPrice($prodwbs->price);
            $produto->setmktQuantity($prodwbs->qty);
            $produto->setmktStatus($prodwbs->status);
            if (isset($prodwbs->variations)) {
                $produto->setmktVariations($prodwbs->variations);
                $produto->setProductType(Type_ProdutoMkt::Tp_MktProd_Grade);
            } else {
                $produto->setProductType(Type_ProdutoMkt::Tp_MktProd_Normal);
            }

            return $produto;
        } else {
            if ($this->httpcode == TypeSkyHubHttpCode::Tp_NaoEncontrado) {
                throw new ExceptionProductNotExists($this->error);
            } else {
                throw new exception($this->error);
            }
        }
    }

    public function setAtualizarProduto(MktProduto $produto, $data = array())
    {
        $this->load->helper('ftr_geral');

        if ($produto->getPrice() <= 0) {
            throw new exception("Não é possivel sincronizar produtos com o preço negativo ou igual a 0!");
        }

        $jsonSend = array();

        if ($produto->getDepartamento() !== null) {
            $deptoName = $produto->getDepartamento()->getName();
        } else {
            $deptoName = '';
        }

        $categories = array();
        if ($produto->getGrupo() !== null) {
            $GrupoName = $produto->getGrupo()->getName();
            $SubGrupoName = $produto->getSubGrupo()->getName();
            $codeCats = (($produto->getDepartamento() !== null) ? $produto->getDepartamento()->getCode() : '')
                . $produto->getGrupo()->getCode()
                . $produto->getSubGrupo()->getCode();

            $categories[] = array(
                "code" => $codeCats,
                "name" => $deptoName . (empty($deptoName) ? '' : ' > ') . $GrupoName . ' > ' . $SubGrupoName
            );
        }

        if ($produto->hasVariations()) {
            $addedVars = false;

            foreach ($produto->getVariacao() as $variacao) {

                $variationsItens = array();
                $aux = array();
                $variations_tipos = array();
                $list_images_vars = array();

                if (!empty($variacao->getCor())) {
                    $variationsItens[] = array(
                        "key" => (!empty($variacao->getTemplateID())) ? 'C' . $variacao->getTemplateID() : 'C0',
                        "value" => $variacao->getCor()
                    );
                    $variations_tipos[((!empty($variacao->getTemplateID())) ? 'C' . $variacao->getTemplateID() : 'C0')] = array(
                        "label" => ((!empty($variacao->getTemplateID())) ? $variacao->getTemplateCor() : 'Cor'),
                        "name" => ((!empty($variacao->getTemplateID())) ? 'C' . $variacao->getTemplateID() : 'C0')
                    );
                }

                if (!empty($variacao->getTamanho())) {
                    $variationsItens[] = array(
                        "key" => (!empty($variacao->getTemplateID())) ? 'S' . $variacao->getTemplateID() : 'S0',
                        "value" => $variacao->getTamanho()
                    );
                    $variations_tipos[((!empty($variacao->getTemplateID())) ? 'S' . $variacao->getTemplateID() : 'S0')] = array(
                        "label" => ((!empty($variacao->getTemplateID())) ? $variacao->getTemplateTamanho() : 'Tamanho'),
                        "name" => ((!empty($variacao->getTemplateID())) ? 'S' . $variacao->getTemplateID() : 'S0')
                    );
                }

                if (!empty($variacao->getEspecificacao())) {
                    $variationsItens[] = array(
                        "key" => (!empty($variacao->getTemplateID())) ? 'SP' . $variacao->getTemplateID() : 'SP0',
                        "value" => $variacao->getEspecificacao()
                    );
                    $variations_tipos[((!empty($variacao->getTemplateID())) ? 'SP' . $variacao->getTemplateID() : 'SP0')] = array(
                        "label" => ((!empty($variacao->getTemplateID())) ? $variacao->getTemplateEspecificacao() : 'Especificação'),
                        "name" => ((!empty($variacao->getTemplateID())) ? 'SP' . $variacao->getTemplateID() : 'SP0')
                    );
                }

                //O preço precisa ser passado como uma variação
                $variationsItens[] = array(
                    "key" => "price",
                    "value" => $variacao->getValor()
                );

                $variationsItens[] = array(
                    "key" => "status",
                    "value" => ($variacao->getStatus() == TypeProduct_Status::Tp_Habilitado) ? TypeSkyHub_Status::Tp_Habilitado : TypeSkyHub_Status::Tp_Desabilitado
                );

                $aux['specifications'] = $variationsItens;
                $aux['qty'] = $variacao->getQuantity() < 0 ? 0 : $variacao->getQuantity();


                $imagesProd = $this->convertPicturesObject($variacao->getImagens());
                if (Count($imagesProd) > 0) {
                    foreach ($imagesProd as $key => $img) {
                        $list_images_vars[] = strstr($img, '?versao', true);
                    }
                }

                $aux['images'] = $list_images_vars;

                $auxMktId = ($variacao->getMktVariation_id() != null) ? $variacao->getMktVariation_id() : 'P' . $variacao->getProductid();

                $aux['sku'] = $auxMktId;
                $aux['ean'] = $variacao->getCodigoBarra();

                $variacao->setMktVariation_id($auxMktId);

                $variations[] = $aux;
                $addedVars = true;
            }
        }
        // Fim add variações

        $specifications[] = array(
            "key" => "crossdocking",
            "value" => "0"
        );

        if ($produto->hasParam('origem_produto')) {
            $specifications[] = array(
                "key" => "origem_produto",
                "value" => $produto->getParam('origem_produto')
            );
        }

        if ($produto->hasParam('garantia')) {
            $specifications[] = array(
                "key" => "garantia",
                "value" => $produto->getParam('garantia')
            );
        }

        if ($produto->hasParam('parcelamento_maximo')) {
            $specifications[] = array(
                "key" => "parcelamento_maximo",
                "value" => $produto->getParam('parcelamento_maximo')
            );
        }

        //QUANTIDADE DA EMBALAGEM
        if ($produto->hasParam('quantity_unit')) {
            $specifications[] = array(
                "key" => "quantity_unit",
                "value" => $produto->getParam('quantity_unit')
            );
        }

        if ($produto->hasParam('nbm')) {
            $specifications[] = array(
                "key" => "nbm",
                "value" => $produto->getParam('nbm')
            );
        }
        $list_images = array();
        $imagesProd = $produto->getPictures()->getImagens();
        if (Count($imagesProd) > 0) {
            foreach ($imagesProd as $key => $img) {
                $list_images[] = $img->getLinkSemMd5();
            }
        }

        $title = $produto->getCustomTitle();
        if ((!isset($title)) || (empty($title))) {
            $title = $produto->getName();
        }

        $initial_description = $this->config->get('skyhub_initial_description') ?? '';
        $final_description = $this->config->get('skyhub_final_description') ?? '';

        trim($initial_description) != '' ? $initial_description = trim($initial_description) . "\n\n" : $initial_description = '';
        trim($final_description) != '' ? $final_description = trim($final_description) : $final_description = '';
        if (!empty($final_description) && !empty($produto->getDescription())) {
            $final_description = "\n\n" . $final_description;
        }

        $description = $initial_description . $produto->getDescription() . $final_description;

        $jsonSend['product'] = array(
            'name' => $title,
            'qty' => $produto->getQuantity() < 0 ? 0 : $produto->getQuantity(),
            'description' => $description,
            'status' => ($produto->getStatus() == TypeProduct_Status::Tp_Habilitado) ? TypeSkyHub_Status::Tp_Habilitado : TypeSkyHub_Status::Tp_Desabilitado,
            'price' => $produto->getPrice(),
            'promotional_price' => $produto->getPromotional_price(),
            'cost' => $produto->getCost(),
            'weight' => $produto->getWeight(),
            'height' => $produto->getHeight(),
            'width' => $produto->getWidth(),
            'length' => $produto->getLength(),
            'brand' => $produto->getMarca(),
            'ean' => $produto->getCodigoBarra(),
            'categories' => $categories,
            'specifications' => $specifications,
            'images' => $list_images
        );


        if (($produto->hasVariations()) && ($addedVars)) {
            $mktID = ($produto->getMktId() != null) ? $produto->getMktId() : 'G' . $produto->getProductid();

            $jsonSend['product']['variations'] = $variations;
            $jsonSend['product']['variation_attributes'] = array_keys($variations_tipos);

            $this->sincAttributes($variations_tipos);
        } else {
            $mktID = ($produto->getMktId() != null) ? $produto->getMktId() : 'P' . $produto->getProductid();
        }

        $jsonSend['product']['sku'] = $mktID;


        $jsonSend = json_encode($jsonSend);

        if ($produto->getMktId() != null) {
            $retorno = $this->updateProduct($produto->getMktId(), $jsonSend);
        } else {
            $retorno = $this->addProduct($jsonSend);
        }

        if ($this->httpcode == TypeSkyHubHttpCode::Tp_NaoEncontrado) {
            throw new ExceptionProductNotExists('Não foi possível encontrar Product: ' . $produto->getMktId());
        } else {
            if ($retorno) {
                $mktRetorno = $this->getProduto($mktID);
                $produto->setMktRetorno($mktRetorno);
                return $produto;
            } else {
                throw new exception($this->error);
            }
        }

    }

    public function setDesincronizarProduto($marketId, $id)
    {
        $jsonSend = array();

        $mktRetorno = $this->getProduto($marketId);
        $mktRetorno = $mktRetorno->getmktVariations();

        if (isset($mktRetorno) && is_array($mktRetorno)) {
            foreach ($mktRetorno as $variacao) {
                $jsonSend['variation']['specifications'] = array(
                    "key" => "status",
                    "value" => TypeSkyHub_Status::Tp_Desabilitado
                );
                $this->updateVariation($variacao->sku, json_encode($jsonSend));
            }
        }

        $jsonSend = array();
        $jsonSend['product'] = array(
            'status' => TypeSkyHub_Status::Tp_Desabilitado
        );

        $jsonSend = json_encode($jsonSend);

        $retorno = $this->updateProduct($marketId, $jsonSend);

        if ($retorno) {
            return $this->getProduto($marketId);
        } else {
            throw new exception($this->error);
        }
    }

    public function sincAttributes($attributesList)
    {
        //Função utilizada na sincronização automatica e no momento do encio do produto
        $this->load->type('tipomarketplace');
        $attributes_info = $this->db->query("SELECT mkt_code, descricao  FROM oc_marketplace_group_attributes WHERE `mkt_code` in ('" . implode("','", array_keys($attributesList)) . "') and tipo_integracao =" . Type_MarketPlace::Tp_SkyHub)->rows;

        if (!empty($attributes_info)) {


            foreach ($attributes_info as $att) {
                $atts_return[] = $att['mkt_code'];
                $atts_return_descriptions[$att['mkt_code']] = $att['descricao'];
            }
            foreach ($attributesList as $attup) {
                //Atualiza as descrições dos atributos
                if (isset($atts_return_descriptions[$attup['name']]) && $atts_return_descriptions[$attup['name']] <> $attup['label']) {
                    $this->db->query(
                        "UPDATE oc_marketplace_group_attributes SET descricao='" . $attup['label'] . "' where `mkt_code` ='" . $attup['name'] . "'"
                    );
                    if (isset($attup['options']) && is_array($attup['options'])) {
                        $jsonSend['attribute'] = array(
                            "name" => $attup['name'],
                            "label" => $attup['label'],
                            "options" => $attup['options']
                        );
                    } else {
                        $jsonSend['attribute'] = array(
                            "name" => $attup['name'],
                            "label" => $attup['label']
                        );
                    }
                    $this->addAttribute($jsonSend);
                }
            }
            $atts_sinc = array_diff(array_keys($attributesList), array_values($atts_return));
        } else {
            $atts_sinc = array_keys($attributesList);
        }

        if (!empty($atts_sinc)) {
            foreach ($atts_sinc as $key) {
                if (isset($attributesList[$key]['options']) && is_array($attributesList[$key]['options'])) {
                    $jsonSend['attribute'] = array(
                        "name" => $key,
                        "label" => $attributesList[$key]['label'],
                        "options" => $attributesList[$key]['options']
                    );
                } else {
                    $jsonSend['attribute'] = array(
                        "name" => $key,
                        "label" => $attributesList[$key]['label']
                    );
                }

                $this->addAttribute($jsonSend);
                $this->db->query(
                    "INSERT INTO oc_marketplace_group_attributes SET mkt_code ='$key', descricao='" . $attributesList[$key]['label'] . "',tipo_integracao =" . Type_MarketPlace::Tp_SkyHub
                );
            }
        }
    }

    public function addAttribute($jsonSend)
    {
        $jsonSend = json_encode($jsonSend);
        $retorno = $this->createAttribute($jsonSend);

        if ($retorno) {
            return true;
        } else {
            throw new exception($this->error);
        }
    }


    public function getOrder($mktOrderId)
    {
        $this->load->helper('ftr_validacao');
        $jsonOrder = $this->getOrderQueue();

        if (!$jsonOrder instanceOf StdClass) {
            return false;
        } else {
            return $this->orderJsonToObject($jsonOrder);
        }

    }

    public function setEnviarNFEDirect($mktOrderId, $xml_arquivo, $qty_vols, $data_hora_emissao)
    {

        $this->load->dmodel('tool/files');
        $file = $this->dmodel_tool_files->createFile(md5($xml_arquivo), $xml_arquivo, Type_File::Xml, true);

        if($file) {
            $file = $this->makeCurlFile($file);
        }

        $datasend = array (
            'volume_qty' => ($qty_vols == 0) ? 1 : $qty_vols,
            'issue_date' => $data_hora_emissao,
            'file' => $file
        );

        //caso ja tenha uma nota fiscal indicada ao pedido não pode enviar o status order_invoiced novamente para reenviar a nota
        $order = $this->callAPI($this->API_DOMAIN . '/orders/' . $mktOrderId, 'GET', false, $this->header, false, $httpCode);
        if ($order && count($order->invoices) == 0) {
            $datasend['status'] = 'order_invoiced';
        }

        $headerInvoice = array(
            'X-User-Email: ' . $this->config->get('skyhub_email'),
            'x-Api-Key: ' . $this->config->get('skyhub_api_key'),
            'x-accountmanager-key: '.$this->config->get('skyhub_account_manager_key'),
            'Accept: application/json;charset=UTF-8',
            'Content-Type: multipart/form-data'
        );

        $httpCode = false;
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/invoice';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $headerInvoice, true, $httpCode);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '', 'url' => $url, 'metodo' => $metodo,
            'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;
            return $retorno;
        }
    }

    public function setPedidoEntregue($mktOrderId)
    {
        $datasend = array(
            'status' => 'complete'
        );

        $httpCode = false;
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/delivery';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '',
            'url' => $url, 'metodo' => $metodo, 'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;;
            return $retorno;
        }
    }

    public function setPedidoEnvio($mktOrderId, $datasend)
    {
        $httpCode = false;
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/shipments';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '', 'url' => $url, 'metodo' => $metodo,
            'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;;
            return $retorno;
        }
    }

    public function setCancelOrder($mktOrderId)
    {
        $datasend = array(
            'status' => 'order_canceled'
        );

        $httpCode = false;
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/cancel';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '',
            'url' => $url, 'metodo' => $metodo, 'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;;
            return $retorno;
        }
    }

    public function setOrderShipmentException($mktOrderId, $datasend)
    {
        $httpCode = false;
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/shipment_exception';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '',
            'url' => $url, 'metodo' => $metodo, 'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;
            return $retorno;
        }
    }

    public function setOrderConfirmedStock($mktOrderId, $confirmed)
    {
        $httpCode = false;
        $datasend = array(
            'confirmed' => $confirmed
        );
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/confirm_stock ';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '',
            'url' => $url, 'metodo' => $metodo, 'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;
            return $retorno;
        }
    }

    public function setOrderProcessingStore($mktOrderId)
    {
        $httpCode = false;
        $datasend = array(
            'status' => 'processing_store'
        );
        $url = $this->API_DOMAIN . '/orders/' . $mktOrderId . '/process_store  ';
        $metodo = 'POST';
        $retorno = $this->callAPI($url, $metodo, $datasend, $this->header, false, $httpCode, Type_DadosSend::TpDados_Json);

        $this->marketplace->logArray[] = array('tipoEnviado' => Type_LogEnviado::Tp_LogEnviado, 'tipoIntegracao' => Type_MarketPlace::Tp_SkyHub,
            'origem' => __METHOD__, 'tipoLog' => Type_Log::Tp_LogPedido, 'tipoId' => Type_LogId::Tp_LogIdMktPedido, 'entidadeId' => $mktOrderId ?? '',
            'url' => $url, 'metodo' => $metodo, 'httpCode' => $this->httpcode, 'retorno' => $retorno, 'enviado' => $datasend, 'dataHora' => $this->db->dataAtual());

        if (($retorno)) {
            return $retorno;
        } else {
            $retorno['erro'] = $this->error;
            return $retorno;
        }
    }

}