# -- coding: utf-8 --
import re, json
import base64
import traceback
from   generic.gn_api       import    gn_api     
from   generic.gn_request   import    Request     
#from   datetime             import    datetime         
#from   time                 import    sleep     

class mercos (gn_api):
    """Classe responsavel pela integracao com a plataforma Mercos (Meus Pedidos)
    """
    def __init__(self, argv:list):
        
        self.db = False
        setup   = self.setup(argv)
        
        #self.ApplicationToken  = setup[0][  'NMTOKEN1API']#lu80x8vw34eczfskx33t4
        #self.CompanyToken      = setup[0]['NMTOKEN1DADOS']
        
        
        self.server = "app.mercos.com"
        if self.environment_config.get('ambiente') != "P" :
            self.server  = "sandbox.mercos.com"
        
        
        base_url = f"https://{self.server}/api"
        headers = {
                    "Content-Type"     : "application/json"    
                #,   "ApplicationToken" : self.ApplicationToken
                #,   "CompanyToken"     : self.CompanyToken
                ,**self.get_token('ApplicationToken')
                ,**self.get_token('CompanyToken')
                
            }
        self.mercos_request = Request(
                base_url = f"{base_url}/v1/"
            ,   headers  = headers
        ) 
        self.mercos_request_v2 = Request(
                base_url = f"{base_url}/v2/"
            ,   headers  = headers
        ) 
        
        super(mercos, self, ).__init__()
        
    def buscar_pedidos_naoprocessados(self):
        from datetime              import    datetime, timedelta
        from urllib.parse         import    parse_qs
        
        orders = []

        pedidos_ids = self.getDb().select(
                """
                    SELECT 
                        IDAPI, IDSOFTDIB
                    FROM
                        TBRELACIONAID
                    WHERE
                        NMTABELA = 'TBPEDIDOSRETORNO'
                    AND
                        NMNOMEAPI = 'mercos'
                    AND 
                        HASHMD5 = 'REPROCESSAR'
                """
        )

        for pedido in pedidos_ids :
            pedido_params = {k: v[0] for k, v in parse_qs(pedido['IDAPI'], keep_blank_values=True).items()}

            id = pedido_params.get('id')
            alterado_apos = pedido_params.get('alterado_apos')

            ## voltar 1 minuto para garantir que pegue a ultima alteração
            alterado_apos = (datetime.strptime(alterado_apos, "%Y-%m-%d %H:%M:%S") - timedelta(seconds=30)).strftime("%Y-%m-%d %H:%M:%S")

            buscar_pedido = self.mercos_request.doRequest(
                rote = f"pedidos/?alterado_apos={alterado_apos}&status=2&registros_por_pagina=10"
            )

            if buscar_pedido.ok:
                todos_pedidos = buscar_pedido.json()

                pedido = next((pedido for pedido in todos_pedidos if str(pedido['id']) == id), None)

                if pedido:
                    orders.append(pedido)


        return orders
        # self.mercos_request.doRequest("")

    def remover_pedido_reprocessado(self, idapi):
        self.getDb().delete(
            "TBRELACIONAID",
            [
                    "NMNOMEAPI='mercos'"
                ,   "NMTABELA='TBPEDIDOSRETORNO'"
                ,   "HASHMD5='REPROCESSAR'"
                ,   "IDSOFTDIB='FALTANDO_DADOS'"
                ,   f"IDAPI LIKE '%id={idapi}%'"
            ]
        )

    def pedidos_handler(self, data) :
        """Funcao para manipular os dados vim do GET de pedidos de todas as integraçoes
            - Ela grava os dados dos pedidos no sistema Softdib
        Args:
            data (dict): []
        """        

        pedidos_naoprocessados = self.buscar_pedidos_naoprocessados()

        data = pedidos_naoprocessados + data

        # for order in filter(lambda order: order['id'] in [150707617], data): # - mercos
        
        for order in data:

            code = self.jsonValueByPath(self.atualWs.get('identifier','id'),order)
            
            order_already_exists = self.exists(
                    "IDTBPEDIDOSRETORNO"
                ,   "TBPEDIDOSRETORNO"
                ,   [ 
                        f"CDPEDIDOEXTERNO='{code}'"#.format(order[self.atualWs['identifier']])
                    ,   f"NMAPI='{self.apiName}'"#.format(self.apiName)
                ]
            
            )
            
            if order_already_exists:
                continue
            
            order_to_send   = dict()
            try:
                self.current_order = order
                # Ira extrair dodos os dados referente a pedidos e aos items
                # Ele extrai os valores relacionado ao que foi definido no map
                order_to_send['pedido'       ]  = self.call("get_order_data" , self.current_order, is_required = True) #[ self.extractValues(order, 'pedido_fields') ]

                # Existe um tratamento no Ideris, que se o pedido for Mercado Livre e o tipo for igual a FULL ele não irá importar o pedido
                if order_to_send['pedido'       ][0]['CDFRETE'] == 0:
                    continue

                if order_to_send['pedido'][0]['CDUSUARIO']  == '0' or order_to_send['pedido'][0]['CDVENDEDOR']  == '0':
                    self.relatement({
                            "NMNOMEAPI"         : self.apiName                                            
                        ,   "NMTABELA"          : "TBPEDIDOSRETORNO"
                        ,   "IDSOFTDIB"         : "FALTANDO_DADOS"
                        ,   "DTULTIMAALTERACAO" : "now()"
                        ,   "HASHMD5"           : "REPROCESSAR"
                        ,   "IDAPI"             : "id={code}&alterado_apos={alterado_apos}".format(
                            code=order.get("id"), 
                            alterado_apos=order.get("ultima_alteracao")
                        )
                    })
                    continue
            
                order_to_send['itenscarrinho']  = self.call("get_order_items", self.current_order, is_required = True) 
                order_to_send['volumes']        = self.call("get_order_volumes", self.current_order, is_required = False) 
                order_to_send['etiquetas']      = self.call("get_order_etiquetas", self.current_order, is_required = False) 
                
                #continue 
                # funcao para verificar se o codigo do cliente existe no sistema softdib
                if len( order_to_send['pedido'] ) and ( not order_to_send['pedido'][0]['CDCLIENTE']  or self.atualWs.get('alwaysUpdateClient')):
                    
                    cli_data, = order_to_send['pedido']
                    #cli_data['IDCLIENTEEXTERNO'] = ''
                    #if self.hasAttr("customer_data", self) :
                        # Funcao para recuperar os dados do cliente caso nao venha os dados completo para cadastro e recuperar id do cliente
                        #data = getattr(self, "customer_data")( data )
                    #else :
                    customer_data = self.call('customer_data', cli_data)
                    order_to_send['pedido'][0]['CDCLIENTE'] = self.salvar_cliente_softdib(customer_data or cli_data)
                    
                self.salvar_pedido_softdib(order_to_send)
                self.remover_pedido_reprocessado(code)
                    
            except ZeroDivisionError:
                print(traceback.format_exc())        
            # except Exception as error:
            #     self.createLog("999", str(error))
            #     continue
                #print(error)
                
            
            
            # Limpa a variavel
            self.current_order = {}
        
        
    #!deprecated
    def statusMercosFaturamento(self, data, req) :
        cond    = "Faturado"
        status  = 2 
        if data['excluido'] == True:
            cond   = "Excluido"
            status = 3
        
        mensagem = "Pedido {0} em: {1} - Valor: {2} - Nf: {3} - informações: {4}" \
                    .format(
                        cond,
                        self.mask(data['data_faturamento'], "date"  ),
                        self.mask(data['valor_faturado'], "currency"),
                        data['numero_nf'],
                        data['informacoes_adicionais']
                    )
        
        self.incluirStatusDoPedidoNaMercos(data['pedido_id'], mensagem, status)
        
    
    def customFlagExcluido(self, field) : 
        ''' Retornar true ou false para excluido '''
        return """(
            SELECT 
            (CASE 
                {TABLE}.FGEXCLUIDO WHEN '0' 
                    THEN False ELSE True END
                )
        )""".format(TABLE=self.atualWs['table'])
    
    def faturamento_excluido(self, field):
        ''' Retornar true ou false para excluido '''
        return """(
            SELECT 
            (CASE 
                TBPEDIDOSFATURADOS.FGOPERACAO WHEN '01' 
                    THEN 'false' ELSE  'true' END
                )
        )"""
        
    def nota_fiscal_excluido(self, field):
        return """(
            SELECT 
            (CASE 
                {TABLE}.FGSTATUS WHEN '9999' 
                    THEN False ELSE True END
                )
        )""".format(TABLE=self.atualWs['table'])
        
    #!deprecated
    def clientes_excluido(self, field) :
        
        ''' Retornar true ou false para excluido '''
        return """(
            SELECT 
            (CASE 
                TBCLIENTE.FGSITUACAO WHEN 'A' 
                    THEN False ELSE  True END
                )
        )"""
    
    #!deprecated
    def custom_case_usuarios_clientes(self):
        
        return """
            WHEN NOT EXISTS (
                        SELECT  CLIXVEN.CDCLIENTE
                        FROM    TBCLIENTEXVENDEDOR CLIXVEN
                        WHERE   CLIXVEN.CDCLIENTE = SUBSTRING(TBRELACIONAID.IDSOFTDIB, 1, 6)
                    )
                    THEN
                        'POST'
        
        """
        
        
    
    def db_data_usuarios_clientes(self, db_data):
        
        if self.atualWs.get('table') == 'TBCLIENTEXVENDEDOR':
            #return filter(lambda data: )
            return list(filter(lambda data: data['cliente_id'] and data['usuario_id'] , db_data))
            
        
        
        return None
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO DATA PEDIDO --------------#
    #--------------------------------------------------------#
    def dateLastChanges(self):
        return self.current_order['ultima_alteracao']
        
        
    
    #--------------------------------------------------------#
    #--------- TRATAMENTO CUSTOM WHERER DELETE --------------#
    #--------------------------------------------------------#
    
    def custom_delete_pedidos_status(self) :
        
        return "AND NMAPI='mercos'"
        
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO DELETE -------------------#
    #--------------------------------------------------------#
    

    def beforeDelete_categorias(self, data) :
        
        del data['id']
        del data['categoria_pai_id']
        del data['ultima_alteracao']
        
        return data
    
    def beforeDelete_pedidos_status(self, data) :
        
        del data['id']
        del data['ultima_alteracao']
        
        return data
        
    # Gambiarra porque o mercos nao liberou o method GET pra essa rota...
    def beforeDelete_titulos_vencidos(self, data) :
        
        data = {
            "data_vencimento": "2021-01-01",
            "valor": 0,
            "numero_documento": "0",
            "excluido": True,
            "cliente_id":21039436,
        }
        
        
        return data
        
    def beforeDelete_nota_fiscal(self, data) :
        
        data['excluido'] = True
        
        return data
    
    
    def beforeDelete_clientes(self, data) :
        
        del data['limite_credito']
        data['limite_disponivel'] = 0.0
        data['limite_total'] = 0.0
        
        
        return data
    
    
    def beforeDelete_titulos(self, data) :
        
        data = {
            "data_vencimento": "2021-01-01",
            "valor": 0,
            "numero_documento": "0",
            "excluido": True,
            "cliente_id":1,
        }
        
        
        return data
    
    def send(self ,data) :
        """ Envia dados para uma api - via POST ou PUT """
        
        if 'send' in self.atualWs and self.atualWs['send'] == False:
            return 
            
        
        raw_type_rote       = self.atualWs.get('raw_type')
        raw_type_default    = self.config.get('raw_type')  #raw_type_rote or "json"
        # Por padrao o envio de dados é via json
        raw_type = raw_type_rote or raw_type_default or "json"
        
        # mudar em configuracoes o raw_type se for diferente - ver na documentacao de cada api
        if raw_type == "text" :
            data     =  json.dumps(data)
            raw_type =  "data"
            
        if raw_type == 'urlencoded':
            raw_type = 'data'
            
        
        params = {
                "rote"    : self.current_rote
            ,   "method"  : self.current_method
            ,   raw_type  : data
        }
        
        print(f":params |> {params}\n:data |> {self.current_data}")
        # ! SENDREQUEST
        self.send_response = self.throttling( **params )
        
        if(self.send_response.status_code == 405 and self.current_method == "PUT" and "configuracoes_icms_st" in self.current_rote):
            if(self.autoupdate_configuracoes_icms_st(self.current_rote, data)):
                print(':ok |> Registro atualizado com sucesso!')
                return
        
        
        status_code     = self.send_response.status_code or 0
        response_func   = f"response_code_{status_code}"#.format(status_code)
        
        # Chama uma funcao especifica para cada resposta
        # pode ser generica ou cricada em cada arquivo da api
        call = self.call(response_func, self.send_response)
        
        if call == None:
            #self.response_log(self.send_response)
            print(f":fail |> Funcao status code {status_code} nao criado ainda \n data:{data}")#.format(status_code))            
        
        
    
    def delete_configuracoes_icms_st(self, rote):
        params = {
                "rote"   :   rote
            ,   "method" :   "DELETE"
        }
        
        delete = self.throttling(**params)
        if not delete.ok :
            self.response_log(delete)
            return False
            
        return True
        
    def autoupdate_configuracoes_icms_st(self, rote, data = {}):
        """
            APAGANDO O ANTERIOR
        """
        
        params = {
                "rote"   :   rote
            ,   "method" :   "DELETE"
        }
        
        deleteItem = self.throttling(**params)
        
        if not deleteItem.ok :
            self.response_log(deleteItem)
            return False
        
        """ REMOVENDO DO BANCO DE DADOS  """
        
        tabela = self.atualWs['table'] if not 'alias' in self.atualWs else self.atualWs['alias']
        
        self.getDb().delete(
                "TBRELACIONAID"
            ,   [
                        f"IDAPI='{self.current_data['mercos_id']}'"#.format( applicationId = )
                    ,   f"NMTABELA='{tabela}'"#.format( tabela=tabela )
                    ,   f"NMNOMEAPI='{self.apiName}'"#.format( tabela=tabela )
                ]
        )
        
        """ ATUALIZANDO """
        
        params = {
                "rote"   :   'configuracoes_icms_st'
            ,   "method" :   "POST"
            ,   "data"   :   data
        }
        
        resendItem = self.throttling(**params)
        if not resendItem.ok :
            self.response_log(resendItem)
            return False
           
        """ SALVANDO NO BANCO OS NOVOS PARAMETROS """ 
        
        self.getDb().insert( "TBRELACIONAID", {
            'NMTABELA' : tabela,
            'NMNOMEAPI' : self.apiName,
            'IDAPI' : self.custom_control_id(resendItem),
            'IDSOFTDIB' : self.current_data.get('softdib_id'),
            'HASHMD5' : self.current_data.get('hash_md5'),
            'DTULTIMAALTERACAO' : 'now()'
        })
            
        return True
        
    
    def deleteFromApi(self, **kargs) :
        
        rote = "{rote}/{id}".format(
                rote = self.atualWs['rote']
            ,   id   = kargs['mercos_id']
        )
        
        # CRIADO PARA ATENDER ROTAS QUE TEM DELETE UNICO
        delete_from_rote = self.call("delete_" + self.fixed_rote(), rote)
        
        if delete_from_rote:
            return delete_from_rote
        
        get = self.throttling(**{"rote":rote}) 
        
        if get.status_code != 200 :
            self.response_log(get)
        
        data = self.tryJson(get)
        
        
        func_rote_delete = "beforeDelete_" + self.fixed_rote()
        beforeDelete = self.call( func_rote_delete, data)
        
        if beforeDelete :
            data = beforeDelete
                
        if data and "excluido" in data :
            # Forca excluido, ja que o proposito eh excluir
            data['excluido'] = True
            
            params = {
                    "rote"   :   rote
                ,   "method" :   "PUT"
                ,   "data"   :   json.dumps(data)
            }
            
            
            delete = self.throttling(**params)
            if delete.status_code > 299 :
                self.response_log(delete)
                
            
            return delete.status_code == 200
                
            
        else :
            return False
            
        
    #--------------------------------------------------------#
    #------------------ TRATAMENTO GET -- -------------------#
    #--------------------------------------------------------#
    def usuarios_handler(self, users):

        self.getDb().delete( "TBRELACIONAID",["NMTABELA='TBUSUARIO' AND NMNOMEAPI ='mercos'"])
                
        for user in users :
            
            user_name   = user.get('nome','').split('|')[0]
            user_id      = user.get('id')
            table_name   = self.atualWs.get('table')#['table']
            
            
            if user.get('excluido') :
                self.getDb().delete( "TBRELACIONAID",[f"IDAPI='{user_id}'","NMNOMEAPI='mercos'"]) #.format( user_id=user_id ) ] )
                continue
            
            sql = """ 
                    SELECT
                        CDVENDEDOR
                    FROM
                        TBUSUARIO
                    WHERE
                        1 = 1
                        AND CDUSUARIO = '{user}'
                        AND NMEMAIL = '{email}'
                        AND '{user}' IN (
                        SELECT
                            TB2.CDUSUARIO
                        FROM
                            `TBUSUARIO` AS TB1
                            INNER JOIN TBUSUARIOXEMPRESA AS TB2 ON TB2.CDUSUARIO = TB1.CDUSUARIO
                            AND TB2.CDEMPRESA = '{empresa}'
                            AND TB2.CDFILIAL = '{filial}'
                    );
                    
            """.format( 
                        user    =  user_name.strip()
                    ,   email   =  user.get('email','').strip()
                    ,   empresa =  self.cdempresa
                    ,   filial  =  self.cdfilial  )
            
            
            idsoftdib   = self.getDb().select(sql)
            
            if len(idsoftdib) > 0:
                user = {
                        "NMNOMEAPI"         : "mercos" ,
                        "NMTABELA"          : table_name , 
                        "IDAPI"             : user_id , 
                        "IDSOFTDIB"         : idsoftdib[0]['CDVENDEDOR'] , 
                        "DTULTIMAALTERACAO" : "now()"                            
                }
                
                self.relatement(user)
                
                """ exists = self.exists(
                        "IDAPI"
                    ,   "TBRELACIONAID"
                    ,   [
                            f"IDAPI='{user_id}'"#.format(user_id=user_id)
                        ,   f" NMTABELA='{table_name}'"#.format(table_name=table_name)
                    ])
                    
                if not exists :
                    
                    
                    self.getDb().insert( "TBRELACIONAID", dataFields) """
                    
                
    def nota_fiscal_handler(self, data):
        #"""Tratamento de retorno dos metodos PATCH e POST """
        for dado in data :
            
            output = "|".join([ str(value) for key,value in dado.items()]) + "\n"
        
            if(output):
                flag = "w+" if self.output_count == 0 else "a+"
                self.write_file(output, self.saida_cobol ,flag= flag, encoding='iso-8859-1' )
                self.output_count = +1
                
        return data
                
    def clientes_handler(self, data):
        #"""Tratamento de retorno dos metodos PATCH e POST """
        for dado in data :
            
            output = "|".join([ str(value) for key,value in dado.items()]) + "\n"
        
            if(output):
                flag = "w+" if self.output_count == 0 else "a+"
                self.write_file(output, self.saida_cobol ,flag= flag, encoding='iso-8859-1' )
                self.output_count = +1
                
        return data
        
        
    #--------------------------------------------------------#
    #--------------- TRATAMENTO THROTTLING ------------------#
    #--------------------------------------------------------#
    
    def throttling_rules(self, req) :
        try:
            json = self.tryJson(req)
            #return json.get('tempo_ate_permitir_novamente', 0)
            if "tempo_ate_permitir_novamente" not in  json:
                return 0
            else :
                return json['tempo_ate_permitir_novamente']
        except Exception as e:
            return 0
            
        
        
    def pagination_rules(self, req, data):
        #'pedidos/?status=2&alterado_apos=2021-07-12 15:41:29'

        if req.headers.get('meuspedidos_requisicoes_extras') and self.rote == 'pedidos':
            
            last = data[-1]
            params = self.mountRouteParams({
                "status":"2",
                "alterado_apos": last.get('ultima_alteracao','')
            })
            return f"pedidos/?{params}"
            
        if req.headers.get('meuspedidos_requisicoes_extras') and self.rote == 'usuarios':
            
            last = data[-1]
            params = self.mountRouteParams({
                "alterado_apos": last.get('ultima_alteracao','')
            })
            return f"usuarios/?{params}"
        
        return None
        
        
    def rote_filter_nota_fiscal(self):
            
        sql =  """
            SELECT 
                DTULTIMAALTERACAO 
            FROM 
                TBRELACIONAID
            WHERE 
                1=1 
            AND 
                NMTABELA = '{table}'
            ORDER BY 
                DTULTIMAALTERACAO DESC 
            LIMIT 1;
        """.format(table=self.atualWs['table'])
        
        date = self.getDb().select(sql)
        
        if date:
            alterado_apos = date[0]['DTULTIMAALTERACAO']
        else :
            alterado_apos = "1980-01-01" 
            
        params = self.mountRouteParams({
                "alterado_apos": alterado_apos
            })
        
            
        return f"nota_fiscal/?{params}"
            
                        
        
    #--------------------------------------------------------#
    #--------------- TRATAMENTO PEDIDO/ITEMS- ---------------#
    #--------------------------------------------------------#
    
    
    def get_order_items(self, order) :
        return [ self.extractValues(item, "itenscarrinho_fields") for item in order['items'] if not item['excluido']]
        
    
    def get_order_data(self, order) :
        return [ self.extractValues(order, 'pedido_fields') ]
        
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO STATUS PEDIDO ---------------#
    #--------------------------------------------------------#
    #!deprecated
    def __save_status(self, retorno_cobol):
        
        status = int(self.translate(id = "1", table="TBSTATUS"))
        
        response_orders_status = self.api_request.doRequest(
                rote    = "pedidos/{0}/status".format(retorno_cobol[-1]['CDPEDIDOEXTERNO'])
            ,   method  = "POST"
            ,   data    = json.dumps({
                    "status_id" : status,
                    "anotacao"  : "O pedido foi cadastrado com sucesso em {0}  : Cod. {1} ".format(
                            self.timeNow()
                        ,   retorno_cobol[-1]['CDPEDIDO']
                        
                        )
                })
        )
        
        print("response_orders_status")
        return response_orders_status, response_orders_status.status_code == 200
        
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO FILTROS DE ROTA -------------#
    #--------------------------------------------------------#
    def rote_filter_pedidos(self):
        
        sql =  """
            SELECT 
                DTULTIMAALTERACAO 
            FROM 
                TBRELACIONAID
            WHERE 
                1=1 
            AND 
                NMTABELA = '{table}'
            AND 
                NMNOMEAPI = 'mercos'
            ORDER BY 
                DTULTIMAALTERACAO DESC 
            
            LIMIT 1;
        """.format(table=self.atualWs['table'])
        
        fetch = self.getDb().select(sql)
        
        if len(fetch) :
            alterado_apos = fetch[0]['DTULTIMAALTERACAO']
        else :
            alterado_apos = "1980-01-01"
            
        
        self.createLog("000",alterado_apos)
        return  self.mountRouteParams(
            {
                    "status" : '2'
                ,   "alterado_apos" : alterado_apos
            }
        )
        
    #--------------------------------------------------------#
    #---------- TRATAMENTO CUSTOM DE CUSTOMER----------------#
    #--------------------------------------------------------#
    
    def customer_data(self, data) :
        params = {
            "rote" : "clientes/{cliente}/".format(cliente= self.current_order['cliente_id'])
        }
        response = self.throttling( **params )
        
        if response.status_code == 200 :
            cliente_data = self.tryJson(response)
            
            email       = cliente_data.get('emails',[])
            telefone    = cliente_data.get('telefones',[])
            
            data[    'RAZAO_SOCIAL'] = cliente_data.get('razao_social'      ,'')
            data[   'NOME_FANTASIA'] = cliente_data.get('nome_fantasia'     ,'')
            data[     'TIPO_PESSOA'] = cliente_data.get('tipo'              ,'')
            data[        'CNPJ_CPF'] = cliente_data.get('cnpj'              ,'')
            data[           'RG_IE'] = cliente_data.get('inscricao_estadual','')
            data[        'ENDERECO'] = cliente_data.get('rua'               ,'')
            data[    'ENDERECO_NRO'] = cliente_data.get('numero'            ,'')
            data[     'COMPLEMENTO'] = cliente_data.get('complemento'       ,'')
            data[             'CEP'] = cliente_data.get('cep'               ,'')
            data[          'BAIRRO'] = cliente_data.get('bairro'            ,'')
            data[          'CIDADE'] = cliente_data.get('cidade'            ,'')
            data[          'ESTADO'] = cliente_data.get('estado'            ,'')
            data[           'EMAIL'] = (email and email[0].get('email'      ,'')) or ''
            
            data[        'TELEFONE'] = self.translateByType((telefone and telefone[0].get('numero'  ,'')) or '', 'numero')
            data[             'DDD'] = self.translateByType((telefone and telefone[0].get('numero'  ,'')) or '', 'ddd')
            
            data['IDCLIENTEEXTERNO'] = self.current_order['cliente_id']
            
            
        #print(response)
        return data
        
    #--------------------------------------------------------#
    #---------------- TRATAMENTO ALLOW ROTE -----------------#
    #--------------------------------------------------------#
    def not_allow_rote(self):
        return ['faturamento','altera_pedido/id']
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO CUSTOM -------------------#
    #--------------------------------------------------------#
    
    
    
    def imagens_produto_imagem_base64(self, field):
        ''' corta dados nao necessarios para envio da imagem TESTADO OK'''
        return """ 
            SUBSTRING_INDEX(TBPRODUTOIMAGEM.NMIMAGEM, ',', '-1')
        """
        
    
    def usuarios_clientes_liberado(self, field):
        
        return """ 
            (SELECT 
                    (CASE 
                        WHEN CLI.CDCLIENTE IS NULL 
                            THEN "false" ELSE "true" END
                        )
                ) 
        """
        
    #--------------------------------------------------------#
    #------------------ TRATAMENTO SQL  ---------------------#
    #--------------------------------------------------------#
    #def processSQL_usuarios_clientes(self, sql):
        """ sql = self.replacement({
                "CDEMPRESA" : self.cdempresa
            ,   "CDFILIAL"  : self.cdfilial
            ,   "NMLKGRUPO" : self.nmlkgrupo.upper()
        },sql) 
        sql= sql.format(**{
                "CDEMPRESA" : self.cdempresa
            ,   "CDFILIAL"  : self.cdfilial
            ,   "NMLKGRUPO" : self.nmlkgrupo.upper()
        })
        
        return sql"""
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO RESPONSE  ----------------#
    #--------------------------------------------------------#
    
    def response_code_200(self, response) :
        return super().response_code_201(response)
        
    #--------------------------------------------------------#
    #------------------- TRATAMENTO AFTERSEND  --------------#
    #--------------------------------------------------------#
    
    def afterSend_pedidos_pedido_status(self, data) :
        self.getDb().delete(
                    "TBPEDIDOSSTATUS"
                ,   ["IDTBPEDIDOSSTATUS={}".format(self.current_data['softdib_id'] )]
                )
        pass
        
        
    def atualizar_rastreamento_pedido(self):
        
        pedido_id           = self.current_data.get('pedido_id')
        transportadora_id   = self.current_data.get('transportadora_id')
        rastreamento        = self.current_data.get('rastreamento')
        
        if transportadora_id and rastreamento :
            """Para atualizar o pedido a mercos usa a versao 2 
            """
            self.api_request = self.mercos_request_v2
            
            params = {
                    "rote"    : f"pedidos/{pedido_id}"
                ,   "method"  : "PUT"
                ,   "data"    : json.dumps({
                    "transportadora_id" :transportadora_id,
                    "rastreamento"      :rastreamento,
                })
            }
            
            response_rastreamento = self.throttling(**params) 
            self.createLog(response_rastreamento.status_code,f"Status Rastreamento - Pedido:{pedido_id} - Transportadora - {transportadora_id} - rastreamento - {rastreamento}")
            
        self.api_request = self.mercos_request
    
    
    def afterSend_faturamento(self, data) :
        self.atualizar_rastreamento_pedido()
        
        situation    = "Pedido faturado"
        status  = 2 
        if data['excluido'] :
            
            situation   = "Faturamento excluido"
            status = 3
            
            
            
        self.getDb().insert( "TBPEDIDOSSTATUS", {
                'NMLKGRUPO'         :  self.nmlkgrupo 
            ,   'CDEMPRESA'         :  self.cdempresa 
            ,   'CDFILIAL'          :  self.cdfilial
            ,   'NMAPI'             :  self.apiName 
            ,   'CDPEDIDOEXTERNO'   :  self.current_data['pedido_id']
            ,   'CDPEDIDO'          :  self.current_data['pedido_sd'] 
            ,   'DTSTATUS'          :  "now()" 
            ,   'CDSTATUS'          :  status 
            ,   'NMOBSERVACAO'      :  "{0} em: {1} - Valor: {2} - Nf: {3} - informações: {4}" \
                                        .format(
                                            situation,
                                            self.mask(data['data_faturamento'], "date"  ),
                                            self.mask(data['valor_faturado'], "currency"),
                                            data['numero_nf'],
                                            data['informacoes_adicionais']
                                        )
                
        })
        
        
        
        """ status = int(self.translate(id = status, table="TBSTATUS"))
        
        anotacao = "Pedido {0} em: {1} - Valor: {2} - Nf: {3} - informações: {4}" \
                    .format(
                        cond,
                        self.mask(data['data_faturamento'], "date"  ),
                        self.mask(data['valor_faturado'], "currency"),
                        data['numero_nf'],
                        data['informacoes_adicionais']
                    )
        
        
        params = {
                "rote"    : "pedidos/{0}/status".format(data['pedido_id'])
            ,   "method"  : "POST"
            ,   "data"    : json.dumps({
                    "status_id" : status,
                    "anotacao"  : anotacao
                })
        }
        response = self.throttling(**params)
        return response == 200
        
        print("response_orders_status")
        return  """
        
    
    
    
    def afterSend_produtos(self, data) :
        if data['excluido'] :
            
            self.getDb().delete(
                    "TBRELACIONAID"
                ,   [
                            "NMTABELA='{}'".format(self.atualWs['table'] )
                        ,   "IDAPI='{}'".format(self.current_data['mercos_id'])
                    ]
                )
        
        
    
    def afterSend_transportadoras(self, data) :
        
        if data['excluido'] :
            self.getDb().delete(
                    "TBRELACIONAID"
                ,   [
                            "NMTABELA='{}'".format(self.atualWs['table'] )
                        ,   "IDAPI='{}'".format(self.current_data['mercos_id'])
                    ]
                )
            
        
    
    def afterSend_campos_extras(self, data):
        
        
        _list = self.tryJson(self.send_response)
        
        for index,item in enumerate(_list['itens']) :
            data_relaciona_id = {
                    "NMNOMEAPI"         : self.apiName                                            
                ,   "NMTABELA"          : self.atualWs['table']  + "ITEM"                      
                ,   "IDSOFTDIB"         : self.current_data['itens'][index]['item_id']     
                ,   "DTULTIMAALTERACAO" : "now()"                                             
                ,   "HASHMD5"           : self.current_data['hash_md5']                         
                ,   "IDAPI"             : item 
            }
            
            self.relatement(data_relaciona_id)
        
        
        pass
    
    #--------------------------------------------------------#
    #------------------- TRATAMENTO BEFORESEND --------------#
    #--------------------------------------------------------#
    #? sempre no fim de cada before fazer o return data
    def afterSend_usuarios_clientes(self, data) :
        if not data.get('liberado') :
            self.getDb().delete(
                    "TBRELACIONAID"
                ,   [
                            "IDAPI='{}'"     .format(self.current_data.get('id'))
                        ,   "NMTABELA='TBCLIENTEXVENDEDOR'"
                        ,   "NMNOMEAPI ='mercos'"
                    ]
                )
            
            
        
        
    
    
    def beforeSend_campos_extras(self, data) :
        
        
        if data['tipo'] == '4':
            
            if self.current_data['request_method'] == "PUT" :
                del data['tipo']
            
            del data['exibir_para_cliente']
            
            data['itens'] = list()
            
            sql = """ 
                SELECT 
                        {tabela}.{codigo} AS item_id
                    ,   {tabela}.{descricao} AS descricao
                    FROM {tabela}
            """.format(
                    tabela = self.current_data['tabela']
                ,   codigo = self.current_data['codigo']
                ,   descricao = self.current_data['descricao']
            )
            fetch  = self.getDb().select(sql)
            
            data['itens'] = list()
            for index,item in enumerate(fetch) :
                
                data['itens'].append(
                    {
                        "valor"         : item['descricao']
                    ,   "id"            : int(self.translate(
                                id      = item['item_id']
                            ,   table   = "TBCAMPOSEXTRASITEM"
                            
                        ))
                    ,   "selecionado"   : True if index == 0 else False
                    ,   "ordem"         : index
                    } 
                )
                if self.current_data['request_method'] == "POST" :
                    del data['itens'][index]['id']
                
                
            #data['itens'] = [for index,item in enumerate(fetch) ]
            
            self.current_data['itens'] = fetch
            
            
        else :
            del data['lista_multipla']
            del data['casas_decimais']
            
        return data
        
    
    def beforeSend_clientes_condicoes_pagamento(self, data):
        
        self.beforeSend_delete(data)
            
        return data
        
        
    
    def beforeSend_clientes_tabela_preco(self, data) :
        
        self.beforeSend_delete(data)
            
        return data
        
        
    def beforeSend_delete(self, data) :
        if self.atualWs['control-id'] in data :
                
            self.getDb().delete(
                    "TBRELACIONAID"
                ,   [
                            "IDAPI='{}'"     .format(data[self.atualWs['control-id'] ])
                        ,   "NMTABELA='{}'".format(self.atualWs['table'            ])
                    ]
                )
            
            
        
    def beforeSend_clientes(self, data) :
        if data['segmento_id'] == '':
            del data['segmento_id']
        
        return data
        
    def beforeSend_nota_fiscal(self, data):
        with open(data['arquivo_xml'], "rb") as pdf_file:
            arquivo_xml = base64.b64encode(pdf_file.read())
            arquivo_xml_64 = arquivo_xml.decode('ascii')
            
            data['arquivo_xml'] = arquivo_xml_64
        
        with open(data['arquivo_pdf'], "rb") as pdf_file:
            arquivo_pdf = base64.b64encode(pdf_file.read())
            arquivo_pdf_64 = arquivo_pdf.decode('ascii')
            
            data['arquivo_pdf'] = arquivo_pdf_64
        
        #data['link_xml'] = base64.urlsafe_b64encode(data['link_xml'])
        
        if(self.current_data['request_method'] == "DELETE" or self.current_data['excluido'] == "9"):
            data['excluido'] = True
        else:
            data['excluido'] = False
            
        return data
        
    def beforeSend_titulos_vencidos(self, data):
        if data['arquivo_pdf'] :
            with open(data['arquivo_pdf'], "rb") as pdf_file:
                arquivo_pdf = base64.b64encode(pdf_file.read())
                arquivo_pdf_64 = arquivo_pdf.decode('ascii')
                
                data['arquivo_pdf'] = arquivo_pdf_64
            
            if(self.current_data['request_method'] == "DELETE" or self.current_data['excluido'] == "9"):
                data['excluido'] = True
            else:
                data['excluido'] = False
            
        return data

    def afterSend_titulos_vencidos(self, data):
        import os

        arquivo_pdf_path = ''
        if os.path.isfile(self.current_data.get('arquivo_pdf', '')):
            arquivo_pdf_path = self.current_data.get('arquivo_pdf', '')
        elif os.path.isfile(data.get('arquivo_pdf', '')):
            arquivo_pdf_path = data.get('arquivo_pdf', '')
        else:
            return

        if arquivo_pdf_path == '':
            return

        if arquivo_pdf_path:
            try:
                # Limpa o conteúdo do arquivo PDF, mas mantém o arquivo existente
                with open(arquivo_pdf_path, 'w') as pdf_file:
                    pdf_file.write('')  # Escreve string vazia, zerando o arquivo
                
                self.createLog(200, f"Arquivo PDF limpo com sucesso: {arquivo_pdf_path}")
                
            except IOError as error:
                self.createLog(500, f"Erro ao limpar arquivo PDF {arquivo_pdf_path}: {str(error)}")
            except Exception as error:
                self.createLog(500, f"Erro inesperado ao limpar arquivo PDF: {str(error)}")

          
        
        
        
    
    def beforeSend_categorias(self, data):
        
        if  self.current_data['sub_grupo'] == 0 or self.current_data['request_method'] == 'PUT':
            del data['categoria_pai_id']
        else :
            #sql = "SELECT IDAPI FROM  TBRELACIONAID WHERE 1=1 AND IDSOFTDIB = '{}'".format(data['categoria_pai_id'])
            
            #categoria_pai_id = self.select(sql)
            data['categoria_pai_id'] = self.translate(id = data['categoria_pai_id'], table = "TBGRUPO")
        
        return data
        
    
    #--------------------------------------------------------#
    #------------------- TRATAMENTO BEFOREGET --------------#
    #--------------------------------------------------------#
        
        
    
    
    #--------------------------------------------------------#
    #------------------- RELACIONA ID FUNC HEADER -----------#
    #--------------------------------------------------------#
    
    def custom_control_id(self, response) :
        
        if "MeusPedidosID" in response.headers :
            return response.headers['MeusPedidosID']
        else :
            return self.current_data['mercos_id']
        
        
    #--------------------------------------------------------#
    #---------------------- CUSTOM TRANSLATE ---------------#
    #--------------------------------------------------------#
    
    def tratar_excluido(self, path):
        print(path)
    
    def pedidos_frete(self, campos):
        
        return self.campos_extras_required("TBTIPOFRETE", campos)
        
    
    def campos_extras_required(self, required, campos) :
        
        campo = ''
        for campo in campos :
            
            _id = self.translate(
                    id      =   campo['campo_extra_id']
                ,   table   =   "TBCAMPOSEXTRAS"
                ,   reverse =   True
            )
            select = self.select("SELECT NMTABELA FROM TBCAMPOSEXTRAS WHERE IDTBCAMPOSEXTRAS = '{}' ".format(_id))
            if len(select) and select[0]['NMTABELA'] == required :
                # Ira parar o loop e manter o ultimo valido armazenado na variavel campo
                break
        
        #valor = campo.get('valor') 
        valor = campo.get('valor') if campo != '' else ''
        
        if (valor) :
            return valor[0][0]
        else :
            self.createLog("999",f"Dados incompletos para {required} - Pedido:{self.current_order} ")
            #if valor == '':
            #    self.createLog("999","Dados incompletos para {} ".format(required))
            return 0
            #else:     
            #    raise Exception("Dados incompletos para {} ".format(required))
        
    def observacoes_extras(self, value) :
        
        new_obs = self.observacoes + " - "
        # Pega nome e valor do campo extras que vem do mercos e cria uma string separado por \n
        custom_obs = " - ".join(["{nome}:{valor}".format(
                    nome  = obs['nome' ]
                ,   valor = obs['valor']
            ) for obs in value if  obs['nome'] not in ["Tipo de Frete","Data Prevista para Entrega"]])
            
        if custom_obs :
            new_obs += custom_obs
            
        cleanedObs = self.multi_replace(new_obs, [ ["[",""],["]",""],["'",""] ])
        return cleanedObs
            
        
        
    def pedidos_prev_entrega(self, value) :
        
        dataEntrega = list(filter(lambda campos: campos['nome'] == "Data Prevista para Entrega", value))
        if (dataEntrega):
            return dataEntrega[0]['valor']
        
        return ''
        
        
        
    
    def __del__(self):
        self.createLog("999","Final da exportacao")
    
    
    
    
    
    
    


if __name__ == "__main__":
    pass
    # mercos()
    
    """
        Documentação: https://app.mercos.com/api 
        SandBox Mercos (API ambiente de testes): https://sandbox.mercos.com/api/v1 
        SandBox Sistema: https://sandbox.mercos.com 
        
        Usuário: william@softdib.com.br 
        Senha padrão: 123456 
        
        ApplicationToken: bd361d76-6aaf-11e9-a936-a29009f9c38a 
        CompanyToken: 40e7fd68-6aad-11e9-8c04-a29009f9c38a 
        
        
        Abaixo destaca-se alguns pontos que devem ser considerados durante 
        e na finalização do desenvolvimento da integração: 
        
        1) Limite de requisições: https://mercos.docs.apiary.io/#throttling 
        Deve ser implementado no sistema ERP o limite de requisições 
        para que não permita que o sistema ou o usuário envie requisições 
        que possam impactar o nosso ambiente. Este é um item que se não 
        implementado corretamente poderá ocasionar a reprovação da homologação 
        para trafego de dados em ambiente de produção. 
        
        2) Alguns registros como clientes, produtos, tabelas de preços e pedidos 
        que costumam sofrer muitas alterações, devem ser atualizados com 
        base na Data da última alteração. 
        No link https://mercos.docs.apiary.io/#buscando-informa-es-exemplo-pr-tico
        seguem exemplos de como utilizar este parâmetro nas requisições. 
        É imprescindível a implementação correta deste ponto para somente enviar 
        informações quando de fato ocorrer alteração.
        0,
        
    """
