import time
from  generic.gn_request   import   Request # 
from  generic.gn_api    import   gn_api #
from  generic.gn_eship    import   gn_eship #
from  generic.gn_simple_api     import   simple_api #
from datetime import datetime
#from  generic.gn_simple_api     import   simple_api #

import json
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


#class eship(simple_api, gn_json):
class eship(gn_eship):
    def __init__(self, argv:list):
        self.response = None
        self.db = False
        self.output_count = 0
        self.suffix = "_app_pedidos3" 
        self.unparsed_data = {}
        self.setup(argv)

        
        self.rote_handler()
        
        apiKey = self.get_token_data('apiKey')
        url = self.environment_config.get('url')
                       
        self.eship_request = Request(
            base_url = "{}?api&funcao=webService".format(url),
            params   = {},
            verify= False,
            headers={
                'Api': f"{apiKey}",
                'Content-Type': 'application/json'
            }
        )
         
        super(eship, self, ).__init__(argv)
        print('Fim')

    ######   ######    #####   ######    ##  ##  ########  #####    #####
    ##  ##   ##  ##  ##   ##   ##  ##   ##  ##  #  ##  # ##   ##  ##   ##
    ##  ##   ##  ##  ##   ##   ##  ##   ##  ##     ##    ##   ##  ##
    ##  ##   #####   ##   ##   ##  ##   ##  ##     ##    ##   ##   #####
    #####    ####    ##   ##   ##  ##   ##  ##     ##    ##   ##       ##
    ##       ## ##   ##   ##   ##  ##   ##  ##     ##    ##   ##  ##   ##
    ###      ###  ##   #####   ######     ####     ####    #####    #####

    ## CRIAR PRODUTO
    def beforeSend_PostProduto(self, data):
        if 'unidadeReferencia' in data:
            data['unidadeReferencia'] = self.unidadeReferenciaTable(data['unidadeReferencia'])

        return data
        
    def handle_output_PostProduto(self, data):
        return

    ## ATUALIZAR PRODUTO
    def beforeSend_PutProduto(self, data):
        return data
        
    def handle_output_PutProduto(self, data):
        return
    
     ###  ###   #  #   ###  ###    ##   #  #  ###   ####   ##         ###   ###    ##   ###   #  # #####   ##    ###
    #      #    ## #  #     #  #  #  #  ## #   #      #   #  #        #  #  #  #  #  #  #  #  #  #   #    #  #  #
     ##    #    # ##  #     ###   #  #  # ##   #     #    #  #        ###   ###   #  #  #  #  #  #   #    #  #   ##
       #   #    #  #  #     # #   #  #  #  #   #    #     ####        #     # #   #  #  #  #  #  #   #    #  #     #
    ###   ###   #  #   ###  #  #   ##   #  #  ###   ####  #  #        #     #  #   ##   ###    ##    #     ##   ###

    def post_route_handler_GetProduto(self):

        produtos = self.select(f"""
           SELECT 
                CDPRODUTO
            FROM
                TBPRODUTO
            WHERE
                1 = 1
                AND CDEMPRESA = {int(self.cdempresa)}
                AND CDFILIAL  = {int(self.cdfilial)}
        """)

        for prod in produtos:
            
            req = self.eship_request.doRequest(
                rote=f"GetProduto",
                method="POST",
                json={
                    "codigoProduto": prod['CDPRODUTO']
                }
            )

            dados, status = self.eship_response(req)

            if status == True:
                if len(dados) == 0:
                    self.createLog("438", "Produto: {} - {}: Produto nÃ£o encontrado na eShip".format(prod['CDPRODUTO'], prod['CDPRODUTO'])) 
                    continue
                
                codigo = dados[0].get('codigo')

                exist_relacionaId = self.select(f"""
                    SELECT
                        COUNT(*) AS count
                    FROM
                        TBRELACIONAID
                    WHERE
                        NMNOMEAPI = 'eship'
                        AND NMTABELA = 'TBPRODUTO'
                        AND IDAPI = '{codigo}'
                """)

                if exist_relacionaId[0]['count'] == 0:
                    self.relatement({
                        "NMNOMEAPI"         : "eship",
                        "NMTABELA"          : "TBPRODUTO",
                        "IDAPI"             : codigo,
                        "IDSOFTDIB"         : prod['CDPRODUTO'],
                        "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "HASHMD5"           : "INTEGRADO"
                    })

                    self.createLog("437", "Produto: {} - {}: Relacionamento criado com sucesso".format(codigo, prod['CDPRODUTO']))

     ###  ###   #  #   ###  ###    ##   #  #  ###   ####   ##         ###   ####  ###    ##    ###  ###  #####   ##    ###
    #      #    ## #  #     #  #  #  #  ## #   #      #   #  #        #  #  #     #  #  #  #  #      #     #    #  #  #
     ##    #    # ##  #     ###   #  #  # ##   #     #    #  #        #  #  ###   ###   #  #   ##    #     #    #  #   ##
       #   #    #  #  #     # #   #  #  #  #   #    #     ####        #  #  #     #     #  #     #   #     #    #  #     #
    ###   ###   #  #   ###  #  #   ##   #  #  ###   ####  #  #        ###   ####  #      ##   ###   ###    #     ##   ###

    def post_route_handler_GetDeposito(self):

        req = self.eship_request.doRequest(
            rote=f"GetDeposito",
            method="POST"
        )

        dados, status = self.eship_response(req)

        if status == True:
            if len(dados) == 0:
                self.createLog("438", "DeposÃ­tos: NÃ£o foram encontrados depÃ³sitos na eShip") 
                exit(1)
                        
            for dep in dados:
                exist_relacionaId = self.select(f"""
                    SELECT
                        COUNT(*) AS count
                    FROM
                        TBRELACIONAID
                    WHERE
                        NMNOMEAPI = 'eship'
                        AND NMTABELA = 'TBDEPOSITO'
                        AND IDAPI = '{dep.get('id', '')}'
                """)

                if exist_relacionaId[0]['count'] == 0:
                    self.relatement({
                        "NMNOMEAPI"         : "eship",
                        "NMTABELA"          : "TBDEPOSITO",
                        "IDAPI"             : dep.get('id', ''),
                        "IDSOFTDIB"         : dep.get('descricao', ''),
                        "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "HASHMD5"           : "INTEGRADO"
                    })

                    self.createLog("437", "DepÃ³sito: {} - {}: Relacionamento criado com sucesso".format(dep.get('id', ''), dep.get('descricao', '')))
        return
    
     ###  ###   #  #   ###  ###    ##   #  #  ###   ####   ##   ###          ###  #     ###   ####  #  # #####  ####   ###
    #      #    ## #  #     #  #  #  #  ## #   #      #   #  #  #  #        #     #      #    #     ## #   #    #     #
     ##    #    # ##  #     ###   #  #  # ##   #     #    #  #  ###         #     #      #    ###   # ##   #    ###    ##
       #   #    #  #  #     # #   #  #  #  #   #    #     ####  # #         #     #      #    #     #  #   #    #        #
    ###   ###   #  #   ###  #  #   ##   #  #  ###   ####  #  #  #  #         ###  ####  ###   ####  #  #   #    ####  ###
    
    def post_route_handler_GetCadastro(self):

        req = self.eship_request.doRequest(
            rote=f"GetCadastro",
            method="POST",
            json={
                "quantidadeRegistros": "99"
            }
        )

        dados, status = self.eship_response(req)
        

        if status == True:
            dados = self.eship_pagination(req)

            if len(dados) == 0:
                self.createLog("438", "Clientes: Nao foram encontrados clientes na eShip") 
                exit(1)
                        
            for cliente in dados:
                cnpjCpf = cliente.get('cnpj', '') if cliente.get('cnpj', '') else cliente.get('cpf', '')

                if cnpjCpf == '':
                    self.createLog("438", "Cliente: {} - {}: CNPJ/CPF nao informado".format(cliente.get('codigo', ''), cnpjCpf))
                    continue

                exist_cliente = self.select(f"""
                    SELECT
                        VLCPFCNPJ,
                        CDCLIENTE
                    FROM
                        TBCLIENTE
                    WHERE
                        1 = 1
                        AND CDEMPRESA IN ({int(self.cdempresa)}, 0)
                        AND CDFILIAL IN ({int(self.cdfilial)}, 0)
                        AND VLCPFCNPJ LIKE '%{cnpjCpf}%'
                """)

                if len(exist_cliente) == 0:
                    self.createLog("438", "Cliente: {} - {}: Cliente nao encontrado no banco de dados".format(cliente.get('codigo', ''), cnpjCpf)) 
                    continue

                cdcliente = exist_cliente[0]['CDCLIENTE']

                exist_relacionaId = self.select(f"""
                    SELECT
                        COUNT(*) AS count
                    FROM
                        TBRELACIONAID
                    WHERE
                        NMNOMEAPI = 'eship'
                        AND NMTABELA = 'TBCLIENTE'
                        AND IDAPI = '{cliente.get('id', '')}'
                """)

                if cliente['codigo'] != cdcliente:

                    atualizarCodigoCliente = self.eship_request.doRequest(
                        rote=f"PutCadastro",
                        method="POST",
                        json={
                            "codigo": cdcliente,
                            "id": cliente.get('id', '')
                        }
                    )

                    if atualizarCodigoCliente.ok:
                        self.createLog("437", "Cliente: {} - {}: Codigo atualizado com sucesso para {}".format(cliente.get('id', ''), cliente.get('razaoSocial', ''), cdcliente))


                if exist_relacionaId[0]['count'] == 0:
                    self.relatement({
                        "NMNOMEAPI"         : "eship",
                        "NMTABELA"          : "TBCLIENTE",
                        "IDAPI"             : cliente.get('id', ''),
                        "IDSOFTDIB"         : cdcliente,
                        "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "HASHMD5"           : "INTEGRADO"
                    })

                    self.createLog("437", "Cliente: {} - {}: Relacionamento criado com sucesso".format(cliente.get('id', ''), cliente.get('razaoSocial', '')))
        return
    
     ###  ###   #  #   ###  ###    ##   #  #  ###   ####   ##   ###        #####  ###    ##   #  #   ###  ###
    #      #    ## #  #     #  #  #  #  ## #   #      #   #  #  #  #         #    #  #  #  #  ## #  #     #  #
     ##    #    # ##  #     ###   #  #  # ##   #     #    #  #  ###          #    ###   #  #  # ##   ##   ###
       #   #    #  #  #     # #   #  #  #  #   #    #     ####  # #          #    # #   ####  #  #     #  #
    ###   ###   #  #   ###  #  #   ##   #  #  ###   ####  #  #  #  #         #    #  #  #  #  #  #  ###   #

    def post_route_handler_GetTransporte(self):
        req = self.eship_request.doRequest(
            rote=f"GetTransporte",
            method="POST"
        )

        dados, status = self.eship_response(req)
        

        if status == True:
            dados = self.eship_pagination(req)

            if len(dados) == 0:
                self.createLog("438", "Clientes: Nao foram encontrados Transportadoras na eShip") 
                exit(1)
                        
            for transp in dados:
                codigoTransportadora = transp.get('codigo', '') 

                exist_transp = self.select(f"""
                    SELECT
                        COUNT(*) AS count,
                        VLCPFCNPJ,
                        CDTRANSPORTADOR
                    FROM
                        TBTRANSPORTADOR
                    WHERE
                        1 = 1
                        AND CDEMPRESA IN ({int(self.cdempresa)}, 0)
                        AND CDFILIAL IN ({int(self.cdfilial)}, 0)
                        AND CDTRANSPORTADOR  = '{codigoTransportadora}'
                """)

                if exist_transp[0]['count'] == 0:
                    self.createLog("438", "Transportadora: {} - {}: Transportadora nao encontrado no banco de dados".format(transp.get('codigo', ''))) 
                    continue

                cdtransp = exist_transp[0]['CDTRANSPORTADOR']

                exist_relacionaId = self.select(f"""
                    SELECT
                        COUNT(*) AS count
                    FROM
                        TBRELACIONAID
                    WHERE
                        NMNOMEAPI = 'eship'
                        AND NMTABELA = 'TBTRANSPORTADOR'
                        AND IDAPI = '{transp.get('id', '')}'
                """)

                if exist_relacionaId[0]['count'] == 0:
                    self.relatement({
                        "NMNOMEAPI"         : "eship",
                        "NMTABELA"          : "TBTRANSPORTADOR",
                        "IDAPI"             : transp.get('id', ''),
                        "IDSOFTDIB"         : cdtransp,
                        "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                        "HASHMD5"           : "INTEGRADO"
                    })

                    self.createLog("437", "Transportadora: {} - {}: Relacionamento criado com sucesso".format(transp.get('id', ''), transp.get('razaoSocial', '')))
        return

     ###   ##   #     ###    ##         ####   ### #####   ##    ##   #  #  ####
    #     #  #  #     #  #  #  #        #     #      #    #  #  #  #  #  #  #
     ##   #  #  #     #  #  #  #        ###    ##    #    #  #  #  #  #  #  ###
       #  ####  #     #  #  #  #        #        #   #    #  #  #  #  #  #  #
    ###   #  #  ####  ###    ##         ####  ###    #     ##    ##    ##   ####

    def post_route_handler_GetSaldoEstoque(self):
        params = {k: v for k, v in self.rote_data['path'].items() if v}

        if 'dataInicialEstoque' in params:
            params['dataInicialEstoque'] = self.formatar_data_inicial(params['dataInicialEstoque'])

        if 'dataFinalEstoque' in params:
            params['dataFinalEstoque'] = self.formatar_data_final(params['dataFinalEstoque'])

        consultar = self.eship_request.doRequest(
            rote=f"GetSaldoEstoque",
            method="POST",
            json=params
        )

        if consultar.status_code in [200, 201]:
            
            status, dados = self.eship_response(consultar)

            if status == False:
                self.retornoCobol("ER|" + json.dumps(dados) + "|\n")
                return

            todo_dados = self.eship_pagination(consultar)

            if status:
                for item in todo_dados:
                    retorno_cobol = [
                        "OK",
                        "PROCESSAMENTO OK",
                        item.get('codigo', ''),
                        item.get('dep_deposito_id', ''),
                        item.get('descricaoDeposito', ''),
                        item.get('pro_lote_id', ''),
                        item.get('numero') if item.get('numero', '') else '',
                        item.get('saldo', ''),
                        item.get('saldoentrada', ''),
                        item.get('saldosaida', ''),
                        item.get('saldovirtual', ''),
                        item.get('saldopendente', ''),
                        "",
                        item.get('saldoreservado', ''),
                    ]
                    self.retornoCobol("|".join(map(str, retorno_cobol)) + "|\n")
                    self.output_count += 1
            else:
                self.retornoCobol("ER|" + json.dumps(dados) + "|\n")
        return 
    
    #####  ###    ##   #  #   ###         ##    ###  #  #  ###         ###   ###    ##   ###
      #    #  #  #  #  ## #  #           #  #  #     #  #  #  #        #  #  #  #  #  #  #  #
      #    ###   #  #  # ##   ##         #  #  #     #  #  ###         ###   ###   #  #  #  #
      #    # #   ####  #  #     #        #  #  #     #  #  #           #     # #   #  #  #  #
      #    #  #  #  #  #  #  ###          ##    ###   ##   #           #     #  #   ##   ###

    def post_route_handler_TransferirOcupacaoProduto(self):
        # Aguardar decisão da eShip
        return
    
    def handle_output_TransferirOcupacaoProduto(self, data):
        return
    
    def post_route_handler_OrdemTransferencia(self):
        # Aguardar decisão da eShip
        return

    def handle_output_OrdemTransferencia(self, data):
        return
    
     ##   ###   ###   ####  #  #
    #  #  #  #  #  #  #     ####
    #  #  ###   #  #  ###   ####
    #  #  # #   #  #  #     #  #
     ##   #  #  ###   ####  #  #
    
    def post_route_handler_PostOrdem(self):

        data = self.txt_to_dict()
        request_structure   = self.atualWs.get('request')
        dados = data['W'][0]
        data_parsed  = self.parser(dados, request_structure)
        
        produtos = data_parsed.get('produtos', {})
        infosOrdem = data_parsed.get('infosOrdem', {})

        data_parsed['produtos'] = []
        data_parsed['infosOrdem'] = []

        data_parsed['produtos'].append(produtos)
        data_parsed['infosOrdem'].append(infosOrdem)
        data_parsed['numeroOrigem'] = self.gerarNumeroOrigem()

        empresa = self.select(f"""
            SELECT
                NMRAZAOSOCIAL,
                VLCNPJ,
                NMENDERECO,
                VLENDERECONUMERO,
                NMBAIRRO,
                NMCOMPLEMENTO,
                VLCEP,
                NMCIDADE,
                NMUF
            FROM
                TBEMPRESA
            WHERE
                1 = 1
                AND CDEMPRESA = {int(self.cdempresa)}
                AND CDFILIAL  = {int(self.cdfilial)}
        """)

        data_parsed["cadastroDestinatario"] = {}
        data_parsed["cadastroDestinatario"]['endereco'] = {}

        data_parsed['cadastroDestinatario']['endereco']['municipio'] = empresa[0]['NMCIDADE']
        data_parsed['cadastroDestinatario']['endereco']['estado'] = empresa[0]['NMUF']
        data_parsed['cadastroDestinatario']['endereco']['bairro'] = empresa[0]['NMBAIRRO']
        data_parsed['cadastroDestinatario']['endereco']['logradouro'] = empresa[0]['NMENDERECO']
        data_parsed['cadastroDestinatario']['endereco']['numero'] = empresa[0]['VLENDERECONUMERO']
        data_parsed['cadastroDestinatario']['endereco']['cep'] = empresa[0]['VLCEP']
        data_parsed['cadastroDestinatario']['cnpjDestinatario'] = empresa[0]['VLCNPJ']
        data_parsed['cadastroDestinatario']['razaoSocialDestinatario'] = empresa[0]['NMRAZAOSOCIAL']

        self.handle_send(data_parsed)
    
    def handle_output_PostOrdem(self, data):
        return self.response_code_200(self.api_request.req)

     ###  #     ###   ####  #  # #####  ####   ###
    #     #      #    #     ## #   #    #     #
    #     #      #    ###   # ##   #    ###    ##
    #     #      #    #     #  #   #    #        #
     ###  ####  ###   ####  #  #   #    ####  ###

    def beforeSend_PostCadastro(self, data):
        if self.current_data['request_method'] == "PUT":
            self.current_data['request_method'] = "POST"
            self.current_rote = "PutCadastro"

            data['codigoGeral'] = self.current_data.get('codigo', '')

        if data['tipoFiscal'] == 'F':
            del data['cnpj']
            del data['ie']

        if data['tipoFiscal'] == 'J':
            del data['cpf']
            del data['rg']

        if data['tipoFiscal']:
            data['tipoFiscal'] = self.tipoFiscalTable(data['tipoFiscal'])

        if data['status']:
            data['status'] = self.statusTable(data['status'])

        cdtipodefinicao = self.current_data.get('cdtipodefinicao', None)

        if cdtipodefinicao is None:
            if 'tipoCadastro' in data:
                del data['tipoCadastro']
        elif cdtipodefinicao in ["N", "V", "R"]:
            data['cpf'] = None
            data['cnpj'] = None
            data['tipoCadastro'] = None
            data['tipoFiscal'] = 3
            data['razaoSocial'] = None

        cnpjCadastro = self.select(f""" 
            SELECT 
                VLCNPJ 
            FROM 
                TBEMPRESA 
            WHERE 
                1 = 1
                AND CDEMPRESA = 1
                AND CDFILIAL  = 1
        """)

        data['cnpjCadastroSuperior'] = cnpjCadastro[0]['VLCNPJ']

        return data

    def beforeSend_PostEndereco(self, data):
        if self.current_data['request_method'] == "PUT":
            self.current_data['request_method'] = "POST"
            self.current_rote = "PutEndereco"

            data['id'] = self.current_data.get('eship_id', '')

        if self.current_data['tipoFiscal'] == 'F':
            del data['cnpj']

        if self.current_data['tipoFiscal'] == 'J':
            del data['cpf']

        cnpjCadastro = self.select(f""" 
            SELECT 
                VLCNPJ 
            FROM 
                TBEMPRESA 
            WHERE 
                1 = 1
                AND CDEMPRESA = 1
                AND CDFILIAL  = 1
        """)

        data['cnpjCadastroSuperior'] = cnpjCadastro[0]['VLCNPJ']

        return data

    #####  ###    ##   #  #   ###  ###    ##   ###  #####   ##   ###    ##   ###    ##
      #    #  #  #  #  ## #  #     #  #  #  #  #  #   #    #  #  #  #  #  #  #  #  #  #
      #    ###   #  #  # ##   ##   ###   #  #  ###    #    #  #  #  #  #  #  ###   #  #
      #    # #   ####  #  #     #  #     #  #  # #    #    ####  #  #  #  #  # #   ####
      #    #  #  #  #  #  #  ###   #      ##   #  #   #    #  #  ###    ##   #  #  #  #

    def beforeSend_PostTransporte(self, data):
        if self.current_data['request_method'] == "PUT":
            self.current_data['request_method'] = "POST"
            self.current_rote = "PutTransporte"

            data = {
                "transporte": data.get('transporte', ''),
                "nomeTransportadora": data.get('nomeTransporte', ''),
            }

        if self.current_data['request_method'] == 'POST':
            del data['transporte']

        return data

    ##  ##  ########  ######   ####     ######  ########    ##    ######    ######   #####    #####
    ##  ##  #  ##  #    ##      ##        ##    #  ##  #   ####    ##  ##     ##    ##   ##  ##   ##
    ##  ##     ##       ##      ##        ##       ##     ##  ##   ##  ##     ##    ##   ##  ##
    ##  ##     ##       ##      ##        ##       ##     ######   #####      ##    ##   ##   #####
    ##  ##     ##       ##      ##        ##       ##     ##  ##   ####       ##    ##   ##       ##
    ##  ##     ##       ##      ## ##     ##       ##     ##  ##   ## ##      ##    ##   ##  ##   ##
     ####     ####    ######   ######   ######    ####    ##  ##  ###  ##   ######   #####    #####

    def unidadeReferenciaTable (self, value):
        opts = {
            'pol': 1 ,
            'm.': 2 ,
            'mm.': 3 ,
            'cm.': 4 ,
            'kg.': 5 ,
            'g.': 6 ,
            'ton': 7 ,
            'un': 8 ,
            'cmÂ³': 9 ,
            'mÂ³': 10 ,
            'mÂ³': 11 ,
            'mÂ²': 12 ,
            'plt': 13 ,
            'CX': 14 ,
            'mg': 15 ,
            'jar': 16 ,
            'far': 17 ,
            'pec': 18 ,
            'pac': 19 ,
            'pec': 20 ,
            'tlc': 21 ,
            'mi': 23 ,
            'PCT': 75 ,
            'PC': 77 ,
            'UM': 79 ,
            'KG': 81 ,
            'MI': 83 ,
            'ML': 85 ,
            'FL': 87 ,
            'TB': 89 ,
            'JG': 91 ,
            'M': 93 ,
            'ROL': 95 ,
            'PT': 97 ,
            'FR': 99 ,
            'L': 101 ,
            'PAA': 103 ,
            'UN': 105 ,
            'mil': 107 ,
            'DZ': 109
        }

        return opts.get(value, 105)  # Default to 'un' if value not found in opts
        
    def tipoFiscalTable (self, value):
        opts = {
            'J': 1 ,
            'F': 2 ,
        }

        return opts.get(value, 1)
        
    def statusTable (self, value):
        opts = {
            'A': 1 ,
            'I': 2 ,
        }

        return opts.get(value, 1)
    
    def response_code_400(self, req):
        print(req.text)

        return super().response_code_400(req)
    
    def response_code_200(self, req) :
        if req.text:
            retorno = json.loads(req.text)

            if 'erros' in retorno and retorno['erros']:
                req.status_code = 400
                return self.response_code_400(req)

        return super().response_code_201(req)
    
    """
        "erros": [
            {
                'erro': {'mensagem': "Cadastro : '1' -  '12.949.960/0001-81'  jÃ¡ existe", 'codigo': 'MCA0104'}
            }
        ]
    """
    
    def response_code_400(self, response):
        lista_erros = response.json().get('erros', [])

        if lista_erros:
            for erro in lista_erros:
                erro_info = erro.get('erro', {})
                mensagem = erro_info.get('mensagem', '')
                codigo = erro_info.get('codigo', '')

                # Tratamento de erros apenas para cadastro de clientes
                if self.atualWs['table'] == "TBCLIENTE" and not 'alias' in self.atualWs:
                    # Verifica se é erro de cadastro duplicado
                    if codigo == 'MCA0104' and 'já existe' in mensagem:
                        self.handle_cadastro_duplicado(mensagem, json.loads(response.request.body))
                        return
                    
                    if codigo == 'MCA0048': 
                        print(json.loads(response.request.body))
                        self.handle_cadastro_existente_atualizar(json.loads(response.request.body))
                        # self.handle_cadastro_duplicado(mensagem, json.loads(response.request.body))
                        return
                    
                    if codigo == 'MCA9103':
                        # Registro não existe na eShip, verificar se existe usando o CPF/CNPJ
                        self.handle_cadastro_existente_atualizar(json.loads(response.request.body))
                        return
                    
                elif self.atualWs['table'] == "TBCLIENTE" and 'alias' in self.atualWs and self.atualWs['alias'] == 'TBENDERECO':
                    # Verifica se é erro de cadastro duplicado de endereço
                    # END0100 - Endereço já existe para o cadastro
                    if codigo == 'END0100': 
                        self.handle_endereco_existente(json.loads(response.request.body))
                    elif codigo == 'END1504':
                        self.handle_endereco_existente(json.loads(response.request.body))
                    elif codigo == 'MCA0035':
                        print("[INFO] Cliente não existente na base da eShip.")
                    else:
                        print(codigo)

                elif self.atualWs['table'] == "TBTRANSPORTADOR":
                    if codigo == 'TRA0026':
                        self.handle_transportadora_existente(json.loads(response.request.body))
                        return
                    else:
                        print(codigo)

            
            # Se não for erro de duplicação, loga normalmente
            mensagens = [erro.get('erro', {}).get('mensagem', 'Erro desconhecido') for erro in lista_erros]
            mensagem_completa = " | ".join(mensagens)
            self.createLog(529, "Erro na requisição: {}".format(mensagem_completa))

        self.createLog("555", "Erro na requisição: {}".format(response.text))
        return super().response_code_400(response)
    
    def handle_endereco_existente(self, endereco):

        buscar_endereco = self.eship_request.doRequest(
            rote="GetEndereco",
            method="POST",
            json={
                "logradouro": endereco.get('logradouro', ''),
                "numero": endereco.get('numero', ''),
                "bairro": endereco.get('bairro', ''),
                "endereco": None,
            }
        )

        dados, status = self.eship_response(buscar_endereco)

        if not status or len(dados) == 0:
            self.createLog("438", f"Endereço não encontrado na eShip: {endereco.get('logradouro', '')}, {endereco.get('numero', '')} - {endereco.get('bairro', '')}")
            return
        
        cdcliente = self.current_data.get('softdib_id', '')
        
        self.relatement({
            "NMNOMEAPI"         : "eship",
            "NMTABELA"          : "TBENDERECO",
            "IDAPI"             : dados[0].get('id', ''),
            "IDSOFTDIB"         : cdcliente,
            "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "HASHMD5"           : "INTEGRADO"
        })

        print("[TBENDERECO] {} - {}".format(dados[0].get('id', ''), cdcliente))
    
    def handle_transportadora_existente(self, transportadora):
        req_eship = self.eship_request.doRequest(
            rote="GetTransporte",
            method="POST",
            json={
                "codigoTransporte": transportadora.get('codigoTransporte', ''),
            }
        )

        dados_eship, status = self.eship_response(req_eship)

        if not status or len(dados_eship) == 0:
            self.createLog("438", f"Transportadora não encontrada na eShip: {transportadora.get('cnpj', '')}")
            return
        
        codigo_softdib = transportadora.get('codigoTransporte', '')
        id_eship = dados_eship[0].get('id', '')

        #Verifica se já existe o relacionamento
        exist_relaciona = self.select(f"""
            SELECT
                COUNT(*) AS count
            FROM
                TBRELACIONAID
            WHERE
                NMNOMEAPI = 'eship'
                AND NMTABELA = 'TBTRANSPORTADOR'
                AND IDAPI = '{id_eship}'
        """)

        if exist_relaciona[0]['count'] > 0:
            self.createLog("437", f"Relacionamento já existe para {codigo_softdib} - ID eShip: {id_eship}")
            return
        
        # Cria o relacionamento
        self.relatement({
            "NMNOMEAPI"         : "eship",
            "NMTABELA"          : "TBTRANSPORTADOR",
            "IDAPI"             : id_eship,
            "IDSOFTDIB"         : codigo_softdib,
            "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "HASHMD5"           : "INTEGRADO"
        })

        print(f"[TBTRANSPORTADOR] {id_eship} - {codigo_softdib}")
        

    def handle_cadastro_existente_atualizar(self, cliente):

        cnpj = cliente.get('cnpj', '')
        cpf = cliente.get('cpf', '')
        json_send = {}

        if cnpj is not None and cnpj != '':
            json_send['cnpj'] = cnpj

        if cpf is not None and cpf != '':
            # formatar cpf com zeros a esquerda
            json_send['cpf'] = cpf[-11:]

        

        req_eship = self.eship_request.doRequest(
            rote="GetCadastro",
            method="POST",
            json={
                **json_send
            }
        )

        dados_eship, status = self.eship_response(req_eship)

        if not status or len(dados_eship) == 0:
            self.createLog("438", f"Cliente não encontrado na eShip: {cliente.get('cnpj', '') or cliente.get('cpf', '')}")
            return
        
        id_eship = dados_eship[0].get('id', '')
        codigo_softdib = cliente.get('codigo', '')
        codigo_eship = dados_eship[0].get('codigo', '')

        # Atualiza o código do cliente na eShip se necessário

        updateEship = self.eship_request.doRequest(
            rote="PutCadastro",
            method="POST",
            json={
                "identificador_cadastro": id_eship,
                **cliente
            }
        )

        dados_eship, status = self.eship_response(updateEship)

        if status:
            self.createLog("437", f"Código do cliente atualizado na eShip: {codigo_eship} -> {codigo_softdib}")

            print(f"[INFO] Cliente atualizado na eShip com sucesso. ID: {id_eship} SOFTDIB: {codigo_softdib}")

            self.relatement({
                "NMNOMEAPI"         : "eship",
                "NMTABELA"          : "TBCLIENTE",
                "IDAPI"             : id_eship,
                "IDSOFTDIB"         : codigo_softdib,
                "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "HASHMD5"           : "INTEGRADO"
            })

            

    
    def handle_cadastro_duplicado(self, mensagem, cliente):
        try:
            # Consulta o cadastro na eShip para obter o ID
            req_eship = self.eship_request.doRequest(
                rote="GetCadastro",
                method="POST",
                json={
                    "cnpj": cliente.get('cnpj', ''),
                    "cpf": cliente.get('cpf', '')
                }
            )

            dados_eship, status = self.eship_response(req_eship)

            if not status or len(dados_eship) == 0:
                self.createLog("438", f"Cliente não encontrado na eShip: {cliente.get('cnpj', '') or cliente.get('cpf', '')}")
                return

            id_eship = dados_eship[0].get('id', '')
            codigo_softdib = cliente.get('codigo', '')
            codigo_eship = dados_eship[0].get('codigo', '')

            #Verifica se já existe o relacionamento
            exist_relaciona = self.select(f"""
                SELECT
                    COUNT(*) AS count
                FROM
                    TBRELACIONAID
                WHERE
                    NMNOMEAPI = 'eship'
                    AND NMTABELA = 'TBCLIENTE'
                    AND IDAPI = '{id_eship}'
            """)
            
            if exist_relaciona[0]['count'] > 0:
                self.createLog("437", f"Relacionamento já existe para {codigo_softdib} - ID eShip: {id_eship}")
                return
            
            # Atualiza o código do cliente na eShip se necessário
            if codigo_eship != codigo_softdib:
                req_update = self.eship_request.doRequest(
                    rote="PutCadastro",
                    method="POST",
                    json={
                        "codigo": codigo_softdib,
                        "id": id_eship
                    }
                )
                
                if req_update.ok:
                    self.createLog("437", f"Código do cliente atualizado na eShip: {codigo_softdib} -> {codigo_softdib}")
            
            # Cria o relacionamento
            self.relatement({
                "NMNOMEAPI"         : "eship",
                "NMTABELA"          : "TBCLIENTE",
                "IDAPI"             : id_eship,
                "IDSOFTDIB"         : codigo_softdib,
                "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "HASHMD5"           : "INTEGRADO"
            })

            self.createLog("437", f"Relacionamento criado com sucesso: {codigo_softdib} (ID: {id_eship} -> CDCLIENTE: {codigo_softdib})")
    
        except Exception as e:
            self.createLog("555", f"Erro ao consultar cadastro duplicado: {str(e)}")
            import traceback
            self.createLog("555", traceback.format_exc())
            return
            
        #     dados_eship, status = self.eship_response(req_eship)
            
        #     if not status or len(dados_eship) == 0:
        #         self.createLog("438", f"Cliente não encontrado na eShip: {cnpj_formatado}")
        #         return
            
        #     # Pega o primeiro resultado (pode haver múltiplos, filtrar pelo CNPJ exato)
        #     cliente_eship = None
        #     for cadastro in dados_eship:
        #         cnpj_eship = cadastro.get('cnpj', '') or cadastro.get('cpf', '')
        #         if re.sub(r'[^\d]', '', cnpj_eship) == cnpj_limpo:
        #             cliente_eship = cadastro
        #             break
            
        #     if not cliente_eship:
        #         self.createLog("438", f"CNPJ não corresponde aos dados da eShip: {cnpj_formatado}")
        #         return
            
        #     id_eship = cliente_eship.get('id', '')
        #     codigo_eship = cliente_eship.get('codigo', '')
            
        #     # Verifica se já existe o relacionamento
        #     exist_relaciona = self.select(f"""
        #         SELECT
        #             COUNT(*) AS count
        #         FROM
        #             TBRELACIONAID
        #         WHERE
        #             NMNOMEAPI = 'eship'
        #             AND NMTABELA = 'TBCLIENTE'
        #             AND IDAPI = '{id_eship}'
        #     """)
            
        #     if exist_relaciona[0]['count'] > 0:
        #         self.createLog("437", f"Relacionamento já existe para {nome_cadastro} - ID eShip: {id_eship}")
        #         return
            
        #     # Atualiza o código do cliente na eShip se necessário
        #     if codigo_eship != cdcliente:
        #         req_update = self.eship_request.doRequest(
        #             rote="PutCadastro",
        #             method="POST",
        #             json={
        #                 "codigo": cdcliente,
        #                 "id": id_eship
        #             }
        #         )
                
        #         if req_update.ok:
        #             self.createLog("437", f"Código do cliente atualizado na eShip: {codigo_eship} -> {cdcliente}")
            
        #     # Cria o relacionamento
        #     self.relatement({
        #         "NMNOMEAPI"         : "eship",
        #         "NMTABELA"          : "TBCLIENTE",
        #         "IDAPI"             : id_eship,
        #         "IDSOFTDIB"         : cdcliente,
        #         "DTULTIMAALTERACAO" : datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        #         "HASHMD5"           : "INTEGRADO"
        #     })
            
        #     self.createLog("437", f"Relacionamento criado com sucesso: {nome_cadastro} (ID: {id_eship} -> CDCLIENTE: {cdcliente})")
            
        # except Exception as e:
        #     self.createLog("555", f"Erro ao processar cadastro duplicado: {str(e)}")
        #     import traceback
        #     self.createLog("555", traceback.format_exc())
    
    def eship_response(self, req):
        dados = json.loads(req.text)

        if 'erros' in dados and dados['erros']:
            return dados['erros'], False
        
        else: 
            todos_dados = dados['corpo']['body']['dados']
            
            return todos_dados, True

    """
        {
            "erros": null,
            "corpo": {
                "body": {
                    "dadosPaginacao": {
                        "totalRegistros": 104163,
                        "registrosPorPagina": 25,
                        "quantidadePaginas": 4167,
                        "paginaAtual": 1,
                        "objetosDestaPagina": 23,
                        "totalObjetos": 81905
                    },
    """
    def eship_pagination(self, req):
        # Extrai os dados da primeira resposta
        dados_json = json.loads(req.text)
        body = dados_json.get('corpo', {}).get('body', {})
        paginacao = body.get('dadosPaginacao', {})
        dados = body.get('dados', [])

        # Se nÃ£o houver paginaÃ§Ã£o, retorna os dados
        if not paginacao:
            return dados

        total_paginas = paginacao.get('quantidadePaginas', 1)
        pagina_atual = paginacao.get('paginaAtual', 1)

        todos_dados = dados.copy()

        # Busca as prÃ³ximas pÃ¡ginas, se existirem
        while pagina_atual < total_paginas:
            pagina_atual += 1
            # Monta o body para a prÃ³xima pÃ¡gina
            body_paginacao = json.loads(req.request.body) if req.request.body else {}
            body_paginacao['pagina'] = pagina_atual

            url = req.request.path_url.split('funcao=')[1].split('&')[0].replace('webService','')
            method = req.request.method

            # Faz no va requisiÃ§Ã£o usando o mesmo rote e mÃ©todo
            nova_req = self.eship_request.doRequest(
                rote=url,
                method=method,
                json=body_paginacao
            )
            dados_json = json.loads(nova_req.text)
            body = dados_json.get('corpo', {}).get('body', {})
            novos_dados = body.get('dados', [])
            todos_dados.extend(novos_dados)

        return todos_dados    

    def formatar_data_inicial(self, data_str):
        if not data_str or len(data_str) != 8:
            return None
        
        try:
            ano = data_str[:4]
            mes = data_str[4:6]
            dia = data_str[6:8]
            return f"{ano}-{mes}-{dia} 00:00:00"
        except:
            return None   
    
    def formatar_data_final(self, data_str):
        if not data_str or len(data_str) != 8:
            return None
        
        try:
            ano = data_str[:4]
            mes = data_str[4:6]
            dia = data_str[6:8]
            return f"{ano}-{mes}-{dia} 23:59:59"
        except:
            return None
        
    def gerarNumeroOrigem(self):
        timestamp = int(time.time() * 1000)  # Tempo atual em milissegundos
        return str(timestamp)[-8:]  # Retorna os Ãºltimos 8 dÃ­gitos como string
    
    def retornoCobol (self, retorno):
        import unidecode

        flag = "w+" if self.output_count == 0 else "a+"
        self.write_file(unidecode.unidecode(retorno), self.saida_cobol, flag=flag, encoding='iso-8859-1')
        
    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 )
        
        # retrn
        
        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 __del__(self):
        self.createLog("999","Final da exportacao")
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        