#import re, json
import sys, re
from   generic.gn_api       import   gn_api # 
from   generic.gn_request   import   Request # 
import unidecode
import json



class tray(gn_api):
    def __init__(self, argv:list):
        self.db = False
        self.categories = False
        setup, = self.setup(argv)
        self.tray_init(setup)
        
        super(tray, self, ).__init__()
        
        #print('Fim')
    
    def tray_init(self, setup):
        
        tray_url        =  self.get_token_data('url')
        tray_headers    = {
            'Content-Type'  : 'application/x-www-form-urlencoded',
            'Accept': '*/*'
        }
        request_token = Request(
                url         = f"{tray_url}/auth/"
            ,   headers     = tray_headers
            ,   method      = 'POST'
            ,   data      = {
                    **self.get_token('consumer_key')
                ,   **self.get_token('consumer_secret')
                ,   **self.get_token('code')
                    
                }).doRequest()
        
        if not request_token.ok :
            self.createLog( request_token.status_code, f"token: {self.get_token('code')} - {request_token.text}")
            exit(1)
            
        
        #SOMENTE PARA DEBUG :
        """ if request_token.status_code == 201:
            print(request_token) """
            
        
        data_token = self.tryJson(request_token)
        
        #tray_headers['access_token'] = 
        tray_headers['Content-Type'] = 'application/json'
        self.tray_request = Request(
            base_url = tray_url
        ,   headers     = tray_headers
        ,   params  = {
                "access_token":data_token.get('access_token')
            }
        )
        
        
        
    
    
    #--------------------------------------------------------#
    #-----------------TRATAMENTO DOS CUSTOM------------------#
    #--------------------------------------------------------#
    
    ## GERAL ##
    def slug(self, data) :
        return """
            ( LOWER( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( TRIM({}),':','' ),'+','' ), ')','' ),'(','' ),',','' ),'', '' ),' \ / ', '' ), ' "', '' ), '?', '' ), '/', '-' ), '&', '' ), '!', ''), '.', ''), ' ', '-'), '--', '-'), '--', '-')))
        """.format(self.processItem_dbfield(data))
    
    def status_type(self, data):
        
        return """
            (
                SELECT 
                    CASE 
                        WHEN TBSTATUS.DSSTATUS LIKE '%CANCELADO%' THEN 'canceled'
                        ELSE 'open'
                END
                
            )
            
        """
        
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO BEFORE SEND     -------------#
    #--------------------------------------------------------#
    
    def beforeSend_categories(self, data):
        if  self.current_data['sub_grupo'] != 0:
            data['Category']['parent_id'] = self.translate(id = self.current_data.get('parent_id','0'), table = "TBGRUPO")
        return data

    def beforeSend_products(self, data):
        print(data)
        return data    
    
    def beforeSend_products_id_images(self, data):
        images = self.current_data.get('images')
        
        if  images:
            images = images.split('|')
            for i, image in enumerate(images):
                data['Images'][f'picture_source_{i+1}'] = image
            
        self.current_rote = self.current_rote.replace("_id_", f"/{self.current_data['produto_id']}/")
         
        return data
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO FILTROS DE ROTA -------------#
    #--------------------------------------------------------#
    def rote_filter_orders(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" 
        
        return  self.mountRouteParams(
            #{}
            {"status" : "Aguardando envio","modified": alterado_apos } # Padrão
            #{"status" : "A enviar", "modified": alterado_apos } # CIA LIMP testes
            #{"status" : "A ENVIAR" }
            #{"id" : 33   }
        )
    
    def dateLastChanges(self):
        return self.current_order.get('modified')
    
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO RESPONSE  ----------------#
    #--------------------------------------------------------#
    
    def response_code_200(self, response) :
        return super().response_code_201(response)
    
    
    
    def afterGet_orders(self, data):    
        return data.get('Orders')
        
    
    #--------------------------------------------------------#
    #-----------------TRATAMENTO DOS CUSTOM REPLACEMENT -----#
    #--------------------------------------------------------#
    def get_status_id(self, status):
        try:
            
            if not self.hasAttr("statuses", self):
                res = self.tray_request.doRequest(method='get',rote='/orders/statuses')
                self.statuses = res.json()
                
            statuses    = self.statuses.get('OrderStatuses')
            status_id,  = [item.get('OrderStatus',{}).get('id') for item in statuses if item.get('OrderStatus',{}).get('status') == status] or [None]
            return status_id
        except  Exception as e:
            raise e
        
        
    
    def afterSend_orders_id(self, status) :
        """ Fazer o update de status do pedido na Tray """    
        delete = True
        
        if self.current_data.get('status_id') == 'CANCELADO':
            order_id = self.current_data.get('id')
            res =self.tray_request.doRequest(method='put',rote= f'/orders/cancel/{order_id}')
            delete = res.ok
            
        
        if delete:
            self.getDb().delete(
                "TBPEDIDOSSTATUS"
            ,   [f"IDTBPEDIDOSSTATUS={self.current_data['softdib_id']}"]
        )
    
    
    
    
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO PEDIDO/CUSTOM- ---------------#
    #--------------------------------------------------------#
    def payment_code(self, value):
        value = unidecode.unidecode(value)
        cond_pgto = {}
        if value:
            parcelas = int(self.current_order.get('installment',0))
            if parcelas and parcelas > 1:
                value = f"{value} {parcelas}X"
                
            
            cond_pgto = self.getDb().simple_select(
                    fields      = ["CDCONDPGTO"]
                ,   table       = "TBCONDPGTO"
                ,   where       = [f"DSCONDPGTO ='{value}'"]
                ,   onlyFirst   = True
            )
        
        return cond_pgto.get('CDCONDPGTO', '')
        
        
    def payment_method_rate(self, value):
        return float(self.discount) + abs(float(value))
        
    
    def shipment_tipo_frete(self, value):
        return '9' if 'PARTICULAR' in value or not value else '1'
        
    
    def shipment_transp(self, value):
        cond_pgto = {}
        if value:
            cond_pgto = self.getDb().simple_select(
                    fields      = ["CDTRANSPORTADOR"]
                ,   table       = "TBTRANSPORTADOR"
                ,   where       = [f"NMFANTASIA ='{value}'"]
                ,   onlyFirst   = True
            )
        
        return cond_pgto.get('CDTRANSPORTADOR', '')
        
        
    def tipo_pessoa(self, data):
        tipo_pessoa = self.only_numbers(data)
        return "J" if len(tipo_pessoa) > 11 else "F"
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO PEDIDO/ITEMS- ---------------#
    #--------------------------------------------------------#
    
    def get_order_data(self, order) :
        
        request_order = self.api_request.doRequest(rote=f"orders/{order.get('Order',{}).get('id')}/complete")
        if request_order.ok :
            self.current_order = self.tryJson(request_order).get('Order')
            return [ self.extractValues(self.current_order , 'pedido_fields') ]
        elif request_order.status_code == 401:
            sys.exit()
            
        
        return False
    
    def get_order_items(self, order) :
        return [ self.extractValues(item, "itenscarrinho_fields") for item in order['ProductsSold']]
        
        
    def only_numbers(self, data):
        return  re.sub(r'[^\d]','',data)
    
    def para_numero(self, value):
        return value
    
    def delete_products(self, rote):
        params = {
                "rote"   : rote
            ,   "method" : "PUT"
            ,   "data"   : json.dumps({
                "available": 0
            })
        }
        
        delete = self.throttling(**params)
        
        if not delete.ok :
            self.response_log(delete)
            return False
            
        return True
    
    def deleteFromApi(self, **kargs) :

        # Debug
        # if kargs['softdib_id'] != "0000003":
        #     return False
        
        rote = "{rote}/{id}".format(
                rote = self.atualWs['rote']
            ,   id   = kargs['tray_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
    
    # ------------------------------------------------------ #
    # -------------------- HANDLERS ------------------------ #
    # ------------------------------------------------------ #
    
    def categories_handler(self, data):
        return data
    
    def sync_categoria(self, value):
        
        if not self.categories:        

            listCategories = 1
            pageFinded = 1
            tmpList = []
            
            while listCategories != 0:

                req_categories = self.api_request.doRequest(rote=f"categories?page={pageFinded}&limit=50")

                if req_categories.ok :

                    dados = json.loads(req_categories.text)

                    tmpList = tmpList + dados['Categories']

                    listCategories = len(dados['Categories'])
                    pageFinded += 1
                    
            self.categories = tmpList
                # if self.categories['paging']['page']

        def categoria_na_string(string, valor_procurado):
            # Padronizando a expressão regular para buscar o valor específico
            regex = r'\b' + re.escape(valor_procurado) + r'\b'
            # Procurando por correspondências na string
            correspondencias = re.findall(regex, string)
            
            return bool(correspondencias) 
                
        if self.categories:
            category = list(filter(lambda obj: categoria_na_string(obj.get('Category')['small_description'], value), self.categories))
            category_id = ""
            
            if category:
                category_id = category[0].get('Category').get('id')
            else:
                category_id = self.db.select(self.translate(id=value, table='TBGRUPO', sql=True))
                
                if category_id:
                    category_id = category_id[0]['IDAPI']
                
            return category_id
        
    def custom_control_id_products_id_images(self, response):
        return self.current_data['produto_id']
        
        
    # Apenas para recuperar o id externo do cliente
    """ def customer_data(self, data) :
        data['IDCLIENTEEXTERNO'] = self.current_order['Customer']['id']
        return data """
    
    
    def __del__(self):
        self.createLog("999","Final da exportacao")
        