
"""
acesso para verificar pedidos da Neogrid
https://id.neogrid.com/identity/login
usuario:pedidos@latinex.com.br
senha: L@tinex20
"""




# pip3 install xmljson

#   'docNum'
#   |   '-->'$'
#   'document'
#   |-->content
#   |   |-->ORDER
#   |   |   |-->CABECALHO
#   |   |   |   |-->FUNCAO_MENSAGEM
#   |   |   |   |-->TIPO_PEDIDO
#   |   |   |   |-->NUM_PEDIDO_COMPRADOR
#   |   |   |   |-->NUM_PEDIDO_SISTEMA_EMISSAO
#   |   |   |   |-->DATA_HORA_EMISSAO_PEDIDO
#   |   |   |   |-->DATA_HORA_INICIAL_ENTREGA
#   |   |   |   |-->DATA_HORA_FINAL_ENTREGA
#   |   |   |   |-->NUM_CONTRATO
#   |   |   |   |-->LISTA_PRECOS
#   |   |   |   |-->EAN_FORNECEDOR
#   |   |   |   |-->EAN_COMPRADOR
#   |   |   |   |-->EAN_COBRANCA_FATURA
#   |   |   |   |-->EAN_ENTREGA
#   |   |   |   |-->CNPJ_FORNECEDOR
#   |   |   |   |-->CNPJ_COMPRADOR
#   |   |   |   |-->CNPJ_COBRANCA_FATURA
#   |   |   |   |-->CNPJ_ENTREGA
#   |   |   |   |-->TIPO_COD_TRANSPORTADORA
#   |   |   |   |-->COD_TRANSPORTADORA
#   |   |   |   |-->NOME_TRANSPORTADORA
#   |   |   |   |-->CONDICAO_ENTREGA
#   |   |   |-->DESCONTO_ENCARGO
#   |   |   |   |-->PERC_DESC_COMERCIAL
#   |   |   |   |-->PERC_DESC_FINANCEIRO
#   |   |   |   |-->PERC_DESC_PROMOCIONAL
#   |   |   |   |-->PERC_ENCARGOS_FINANCEIROS
#   |   |   |   |-->PERC_ENCARGOS_FRETE
#   |   |   |   |-->PERC_ENCARGOS_SEGURO
#   |   |   |   |-->VALOR_DESC_COMERCIAL
#   |   |   |   |-->VALOR_DESC_FINANCEIRO
#   |   |   |   |-->VALOR_DESC_PROMOCIONAL
#   |   |   |   |-->VALOR_ENCARGOS_FINANCEIROS
#   |   |   |   |-->VALOR_ENCARGOS_FRETE
#   |   |   |   |-->VALOR_ENCARGOS_SEGURO
#   |   |   |-->ITENS
#   |   |   |   |-->ITEM
#   |   |   |   |   |-->NUM_SEQUENCIAL_LINHA_ITEM
#   |   |   |   |   |-->NUM_ITEM_NO_PEDIDO
#   |   |   |   |   |-->QUALIFICADOR_ALTERACAO
#   |   |   |   |   |-->TIPO_COD_PRODUTO
#   |   |   |   |   |-->COD_PRODUTO
#   |   |   |   |   |-->DESCRICAO_PRODUTO
#   |   |   |   |   |-->REFERENCIA_PRODUTO
#   |   |   |   |   |-->UNID_MEDIDA
#   |   |   |   |   |-->NUM_UNID_CONSUMO_EMBAL_PEDIDA
#   |   |   |   |   |-->QUANTIDADE_PEDIDA
#   |   |   |   |   |-->QUANTIDADE_BONIFICADA
#   |   |   |   |   |-->QUANTIDADE_TROCA
#   |   |   |   |   |-->TIPO_EMBAL
#   |   |   |   |   |-->NUM_EMBAL
#   |   |   |   |   |-->VALOR_BRUTO_LINHA_ITEM
#   |   |   |   |   |-->VALOR_LIQUIDO_LINHA_ITEM
#   |   |   |   |   |-->PRECO_BRUTO_UNIT
#   |   |   |   |   |-->PRECO_LIQUIDO_UNIT
#   |   |   |   |   |-->BASE_PRECO_UNIT
#   |   |   |   |   |-->UNID_MEDIDA_BASE_PRECO_UNIT
#   |   |   |   |   |-->VALOR_UNIT_DESC_COMERCIAL
#   |   |   |   |   |-->PERC_DESC_COMERCIAL_ITEM
#   |   |   |   |   |-->VALOR_UNIT_IPI
#   |   |   |   |   |-->ALIQUOTA_IPI
#   |   |   |   |   |-->VALOR_UNIT_DESP_ACES
#   |   |   |   |   |-->VALOR_ENCARGO_FRETE
#   |   |   |   |   |-->GRADE
#   |   |   |   |   |-->CROSSDOCKING
#   |   |   |-->PAGAMENTO
#   |   |   |   |-->CONDICOES_PAGAMENTO
#   |   |   |   |   |-->CONDICAO_PAGAMENTO
#   |   |   |   |   |-->DATA_VENCIMENTO
#   |   |   |   |   |-->NUM_PERIODOS
#   |   |   |   |   |-->PERC_PAGAR_VALOR_FATURADO
#   |   |   |   |   |-->REFERENCIA_DATA
#   |   |   |   |   |-->REFERENCIA_TEMPO
#   |   |   |   |   |-->TIPO_PERIODO
#   |   |   |   |   |-->VALOR_PAGAR
#   |   |   |-->SUMARIO
#   |   |   |   |-->VALOR_TOTAL_ABATIMENTOS
#   |   |   |   |-->VALOR_TOTAL_DESC_COMERCIAIS
#   |   |   |   |-->VALOR_TOTAL_DESP_ACES_NAO_TRIB
#   |   |   |   |-->VALOR_TOTAL_DESP_ACES_TRIB
#   |   |   |   |-->VALOR_TOTAL_ENCARGOS
#   |   |   |   |-->VALOR_TOTAL_IPI
#   |   |   |   |-->VALOR_TOTAL_MERCADORIAS
#   |   |   |   |-->VALOR_TOTAL_PEDIDO



import contextlib
import OpenSSL.crypto
import os 
import requests
import ssl
import tempfile

import importlib
generic = importlib.import_module('generic')
# from generic.gn_ws import gn_ws # 


# import generic 
from  generic import gn_xml
# import generic.gn_xml

import requests, html, re, json

from xmljson import badgerfish as bf
from xmljson import parker, Parker
from xml.etree.ElementTree import fromstring
from generic import gn_sendPedidos
from generic.gn_mysql import gn_mysql # 
from generic.JsonByPath import JsonByPath #
from generic.pfx_to_pem import pfx_to_pem #
from datetime import datetime 


import os, ssl
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and getattr(ssl, '_create_unverified_context', None)):
    ssl._create_default_https_context = ssl._create_unverified_context



""" 
    TODO: Criar mapa
    Desenvolver um mapa com um depara para a integracao neogrid, pode-se usar regex
"""

class neogrid:
    """[summary]
    
    Arguments:
        gn_ws {[type]} -- [description]
    """
    def __init__(self, argv:list):
        # TODO: modo debug
        # Criar um modo debug com a url de homologacao
        
        """
            TESTE
            http://as2-teste.neogrid.com:8383/ws/neogrid.webedi.Neogrid.webservice3:neogrid?WSDL
            https://as2-teste.neogrid.com/ws/neogrid.webedi.Neogrid.webservice3:neogrid?WSDL
            
            PRODUÇÃO
            http://as2edi.neogrid.com:8383/ws/neogrid.webedi.Neogrid.webservice3:neogrid?WSDL
            https://as2edi.neogrid.com/ws/neogrid.webedi.Neogrid.webservice3:neogrid?WSDL
            
            TESTE
            HTTP  http://as2-teste.neogrid.com:8383/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port
            HTTPS https://as2-teste.neogrid.com:443/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port
            
            PRODUÇÃO
            HTTP  http://as2edi.neogrid.com:8383/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port
            HTTPS https://as2edi.neogrid.com:443/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port
        """
        self.db = False
        self.apiName   = argv[1] # Nome da api
        self.method    = argv[2] # metodo chamado (GET POST PUT DELETE)
        self.rote      = argv[3] # Rota chamada, se ALL, fazer todos
        self.nmbanco   = argv[4] # Banco de Dados   
        self.nmlkgrupo = argv[5] # posicionamento de grupo   
        self.cdempresa = argv[6] # posicionamento de empresa 
        self.cdfilial  = argv[7] # posicionamento de filial  
        self.saida     = argv[8] # Arquivo de saida
        self.debug     = True if  argv[-1] == 'debug' else False  
        
        
        self.database_db = self.nmbanco.lower() + '_app_pedidos3'
        
        self.createLog("000","inicio do processo")
        # TODO: parametrizar entrada via linha de comando
        #self.cdempresa = '1'
        #self.filial  = '1'
        empresa = self.getDb().select("""
            SELECT 
                VLCNPJ, NMTOKEN2API ,FGAMBIENTE2
            FROM 
                TBEMPRESA 
            WHERE
                1=1 
            AND
                NMLKGRUPO ='{lkgrupo}' 
            AND 
                CDEMPRESA = '{empresa}'
            AND 
                CDFILIAL = '{filial}'
            """.format(
                    lkgrupo = self.nmlkgrupo
                ,   empresa = self.cdempresa  
                ,   filial  = self.cdfilial 
            ))
        
        if not len(empresa) :
            exit()
        
        self.token    = empresa[0]['NMTOKEN2API'] #or "MDU1NDA0MDkwMDAxMTQjZWRpX2xhdGluZXg6MDE2OTEwNDE"
        self.cnpj     = empresa[0]['VLCNPJ']
        self.ambiente = empresa[0]['FGAMBIENTE2'] 
        
        if self.ambiente == 'H':
            self.url = 'https://as2-teste.neogrid.com:443/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port'
            
        
        else :
            self.url = 'https://as2edi.neogrid.com:443/ws/neogrid.webedi.Neogrid.webservice3:neogrid/neogrid_webservice3_wsdl_Port'
            
        
        print("url" + self.url)
        
        
        
        self.auth = {
            "empresa" :     self.cdempresa      , 
            "filial"  :     self.cdfilial       , 
            "user"    :     "SAC"               , 
            "passw"   :     "5680"              , 
            "lkgp"    :     self.nmlkgrupo      , 
            "banco"   :     self.nmbanco        , 
            "apiname" :     self.apiName        ,
        }
        
        
        
        self.get_ws()
        
        # self.setAuth1("05540409000114#edi_latinex", "01691041")
        # self.setAuth2(usr="05540409000114#edi_latinex", psw="01691041")
        # usuário: 07526557000452#WSLatinex
        # senha: WSL@t1n3x
        
    #! Não esta mais sendo usado esta funcao
    def get_from_xml(self, pxpath, document):
        xpaths = pxpath.split('/')
        
        for xpath in xpaths:
            if xpath in document:
                document = document[xpath]
            else:
                return "NAO ENCONTRADO"
            
        return document['$'] if '$' in document else ' ' 
        
        
    def jsonValueByPath(self, path ,json):
        Json = JsonByPath(path=path, json=json)
        return Json.value
        
    def getDb(self):
        if self.db == False :
            self.db = gn_mysql(
                self.nmlkgrupo , 
                self.database_db,
                self.debug
            ) 
            
        
        return self.db
        
    
    def get_ws(self):
        
        
        # SOAPAction: "neogrid_webservice3_wsdl_Binder_setStatusDoc"
        xml = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                xmlns:wsdl="http://motor.viveiro.local/neogrid/webservice3/wsdl">
                <soapenv:Header/>
                <soapenv:Body>
                    <wsdl:getDocsFromEDI>
                        <docType>5</docType>
                        <cnpj>{cnpj}</cnpj>
                        <docsQty>50</docsQty>
                        <zip>false</zip>
                    </wsdl:getDocsFromEDI>
                </soapenv:Body>
            </soapenv:Envelope>
        """.format(cnpj=self.cnpj)
        
        
        action = 'neogrid_webservice3_wsdl_Binder_getDocsFromEDI'
        
        req = self.comunicar(self.url, action, xml)
        
        #print(req.text)
        #print(req.headers)
        
        retorno = req.content
        
        
        retorno = retorno.decode('utf-8')
        retorno = html.unescape( retorno ) 
        retorno = retorno.replace("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>", "")
        retorno = retorno.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"      , "")
        retorno = re.sub(r'[\n\r\t]|\\n|\\r|\\t', '', retorno)
        retorno = re.sub(r'>\s+<', '><', retorno)
        retorno = retorno.split( '<files>')[1]
        retorno = retorno.split('</files>')[0]
        retorno = '<files>' + retorno + '</files>'
        # with open('./terotnoXML.xml', 'w+') as f: f.write(retorno); exit()
        # with open('./terotnoXML.xml', 'r') as f: retorno = f.read()
        retorno = self.readFile("./" + self.apiName +"/pedido_teste_carrefour.txt" )
        retorno = bf.data(fromstring(retorno))
        
        self.saveOrders(retorno)
        
        if not retorno['files'] :
            return
            
        
        
        documents = retorno['files']['document']
        
        if isinstance(documents, list) :
            for document in documents :
                self.saveOrders(document)
                
        else :
            self.saveOrders(documents)
        
        
    def saveOrders(self, document) :
        bCabecalho = 'ORDER/CABECALHO/'
        bSumario   = 'ORDER/SUMARIO/'
        bPagamento = 'ORDER/PAGAMENTO/'
        
        envio = {
            "pedido":[],
            "itenscarrinho":[],
        }
        
        self.cdPedido =self.jsonValueByPath('docNum/$', document)
        #print(cdPedido)
        envio['pedido'].append({
            "CDEMPRESA"             : self.cdempresa                                                                     , 
            "CDFILIAL"              : self.cdfilial                                                                      , 
            "IDTBPEDIDO"            : self.cdPedido                                                                         , 
            "VLPEDIDOSISTEMA"       : self.jsonValueByPath(bSumario  +'VALOR_TOTAL_PEDIDO/$'                    , document) , 
            "DTPEDIDO"              : self.jsonValueByPath(bCabecalho+'DATA_HORA_EMISSAO_PEDIDO/$'              , document) , 
            "HRPEDIDO"              : self.jsonValueByPath(bCabecalho+'DATA_HORA_EMISSAO_PEDIDO/$'              , document) , 
            # FIXME: cadastrar cnpj?
            # "CDCLIENTE"             :self.jsonValueByPath(bCabecalho+'CNPJ_COMPRADOR'                        , document) , 
            # "CDCLIENTE"             : "95865572002436" , 
            "CDCLIENTE"             : gn_sendPedidos.get_cliente(self.auth,self.jsonValueByPath(bCabecalho+'CNPJ_COMPRADOR/$', document)) , 
            "CDTRANSPORTADOR"       :self.jsonValueByPath(bCabecalho+'COD_TRANSPORTADORA/$'                    , document) , 
            "CDTRASNPORTADORREDESP" :self.jsonValueByPath(bCabecalho+'COD_TRANSPORTADORA/$'                    , document) , 
            "CDUSUARIO"             : "CRONTAB"                                                                              , 
            "CDVENDEDOR"            : "U01001"                                                                              , 
            "CDCONDPGTO"            :self.jsonValueByPath(bPagamento+'CONDICOES_PAGAMENTO/CONDICAO_PAGAMENTO/$', document) , 
            "VLTOTAL"               :self.jsonValueByPath(bSumario  +'VALOR_TOTAL_PEDIDO/$'                    , document) , 
            "CDFRETE"               :self.jsonValueByPath(bCabecalho+'COD_TRANSPORTADORA/$'                    , document) , 
            "DSOBSPEDIDO"           : " "                                                                              , 
            "VLPERCDESCONTO"        : " "                                                                              , 
            "VLDESCONTO"            : " "                                                                              , 
            "NMCHAVEUNICAPEDIDO"    : " "                                                                              , 
            "CDSEQPEDIDOEXTERNO"    : " "                                                                              , 
            "CDORIGEM"              : " "                                                                              , 
        })
        
        
        items = self.jsonValueByPath("ORDER/ITENS/ITEM", document)#document['content']['ORDER']['ITENS']['ITEM']
        
        
        if isinstance(items, list) :
            envio['itenscarrinho'] = \
                    [self.mount_itens(item) for item in items]
            
        else :
            
            envio['itenscarrinho'] = [self.mount_itens(items)]
            
            
            # print(json.dumps(pedido))
        
        if envio['pedido'][0]['VLTOTAL'] == '' :
            return
            
        
        retornoPedidos = gn_sendPedidos.envio_pedido(self.auth, envio, debug=True)
        
        if retornoPedidos.status_code == 200 :
            created = retornoPedidos.json()
            
            
            if len(created):
                pass
                #self.marcar_pedido(self.cdPedido,self.cnpj,created[-1]['CDPEDIDO'])
            else :
                return
        
        
        
        """ for pedido in pedidos:
            print(pedido['CDPEDIDOEXTERNO'])
            print(pedido['CDPEDIDO']) """
        
    def mount_itens(self, json) :
        return {
            "CDEMPRESA"                 : self.cdempresa , 
            "CDFILIAL"                  : self.cdfilial  , 
            "IDTBPEDIDO"                : self.cdPedido     , 
            "CDPRODUTO"                 : self.jsonValueByPath('COD_PRODUTO/$'                            ,json) , 
            "VLSEQUENCIA"               : self.jsonValueByPath('NUM_SEQUENCIAL_LINHA_ITEM/$'              ,json) , 
            "VLQUANTIDADE"              : self.jsonValueByPath('QUANTIDADE_PEDIDA/$'                      ,json) , 
            "VLPRECOUNITARIO"           : self.jsonValueByPath('PRECO_LIQUIDO_UNIT/$'                     ,json) , 
            "VLPRECOFINAL"              : self.jsonValueByPath('PRECO_BRUTO_UNIT/$'                       ,json) , 
            "VLQUANTIDADEEMBALAGEM"     : self.jsonValueByPath('NUM_UNID_CONSUMO_EMBAL_PEDIDA/$'          ,json) , 
            #FIXME: desconto por item
            # "VLPERCDESCONTO"  : '' , 
            #FIXME: desconto por item
            # "VLDESCONTO"      : '' , 
        }
        
    def marcar_pedido(self, docNum, cnpj, clientIdentifier):
        
        xml = '''
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://motor.viveiro.local/neogrid/webservice3/wsdl">
                <soapenv:Header/>
                <soapenv:Body>
                    <wsdl:setStatusDoc>
                        <docNum>{docNum}</docNum>
                        <cnpj>{cnpj}</cnpj>
                        <clientIdentifier>{clientIdentifier}</clientIdentifier>
                    </wsdl:setStatusDoc>
                </soapenv:Body>
            </soapenv:Envelope>
        '''.format(docNum=docNum, cnpj=cnpj, clientIdentifier=clientIdentifier)
        
        
        action = 'neogrid_webservice3_wsdl_Binder_setStatusDoc'
        response = self.comunicar(self.url, action, xml)
        text = ''
        
        try:
            text = response.json()
        except ValueError:
            text = response.text
            
            if isinstance(xml,str) :
                status = re.findall(r'<status>(.*)</status>',xml)
                
                text = " ".join(map(str, status))
                
                #text =  + "Codigo gerado : {clientIdentifier}"
                text = "{status} - Pedido Gerado no Sistema Softdib: {clientIdentifier}".format(
                            clientIdentifier = clientIdentifier
                        ,   status           = text
                )
            
            
        self.createLog(response.status_code,text)
        print(response)
        
        # SOAPAction: "neogrid_webservice3_wsdl_Binder_setStatusDoc"
        #req = requests.request(
        #    method, 
        #    url, 
        #    data=xml, 
        #    headers=headers,
        #    verify=False, 
        #)
        
        
        
    # TODO: Criar uma classe de integracao XML
    def comunicar(self, url, action, xml):
        
        xml = re.sub(r'\n|\r|\t',   '', xml)
        xml = re.sub(r'\s+'     ,  ' ', xml)
        xml = re.sub(r'>\s+<'   , '><', xml)
        xml = re.sub(r'^\s+<'   ,  '<', xml)
        xml = re.sub(r'>\s+$'   ,  '>', xml)
        
        headers = {
                "Accept-Encoding" : "gzip,deflate"                                            
            ,   "Content-Type"    : "text/xml;charset=UTF-8"                                 
            ,   "SOAPAction"      : '"' + action + '"'                                       
            ,   "Content-Length"  : str(len(xml))                                             
            ,   "Host"            : "as2-teste.neogrid.com:443"  if self.ambiente == 'H' else "as2edi.neogrid.com:443"                             
            ,   "Connection"      : "Keep-Alive"                                              
            ,   "User-Agent"      : "Apache-HttpClient/4.1.1 (java 1.5)"                      
            ,   "Cookie"          : "ssnid="                                                  
            ,   "Cookie2"         : "$Version=1"                                             
            ,   "Authorization"   : "Basic {}=".format(self.token) , 
        }
        #\\192.168.1.1\raiz\home\felipe
        verify = "S:/var/www/html/nf/nfse/certificados/{}_pubKey.pem".format(self.cnpj)
        
        #with pfx_to_pem( path ) as cert :
            
        req = requests.request( 
                "POST"             
            ,   url                
            ,   data=xml           
            ,   headers=headers    
            ,   verify=False      
            #,   cert="cert/neogrid.cer" 
        )
        
        
        
        return req
    
    
    
    
    
    
    def readFile(self, path) :
        try:
            with open(path , 'r', encoding='utf8') as file:
                return file.read() 
        except IOError as error:
            print(error)
            exit()
    """
    .##........#######...######....######.
    .##.......##.....##.##....##..##....##
    .##.......##.....##.##........##......
    .##.......##.....##.##...####..######.
    .##.......##.....##.##....##........##
    .##.......##.....##.##....##..##....##
    .########..#######...######....######.
    """
    
    def println(self, thePrint) :
        
        if self.debug :
            print(thePrint)
        else :
            self.writeLog(str(thePrint), self.config["path_log"])
        
    
    def timeNow(self):
        return datetime.strftime(datetime.now(),'%d/%m/%Y %H:%M:%S')
        
    
    def createLog(self, status_code, mensagem):
        flag = "w+" if status_code == '000' else "a+"
        conteudo = "{timeNow};{status_code};{mensagem}\n".format(timeNow=self.timeNow(),status_code=status_code,mensagem=mensagem)
        self.writeLog(conteudo, self.saida, flag)
        
    
    def writeLog(self, content="", file_name="", flag = "a+") :
        with open(file_name, flag, encoding='utf8') as log :
            log.write(content) 
        
        
    # ------------------------------------------------------------- #    
        
    def __del__(self):
        self.createLog("999","Final da fim do processo")




if __name__ == "__main__":
    neogrid(1)