
import re, json
from   generic.gn_api       import   gn_api # 
from   generic.gn_request   import   Request # 
"""
Link da documentação API
https://app.swaggerhub.com/apis-docs/SpiritShop/SpiritShopAPI/1.0-oas3

Link Admin da loja
http://externo.studiospirit.com.br/trapiche/admin/
usuario softdip e senha q1w2e3


Onda Pro
https://www.ondapro.com.br/admin/index.php?spsr=common/login
tainara
Tai2022!!


tratoraco:
observacao no pedido para tratoraco;
// 
TODO: !Quando implementar avaliar :
    ? Se os metodos padroes atende a empresa em questao
    ? Se o map esta de acordo eliminando e adcionando o que e necessario
    
    
"""
class spirit(gn_api):
    def __init__(self, argv:list):
        self.db = False
        self.zone_file = {}
        self.discount = 0;
        setup, = self.setup(argv)
        
        self.spirit_request = Request(
                base_url = self.environment_config.get('url') #self.api_url_base
            ,   headers  = {
                'Content-Type'  : 'application/json',
                #'key'           : setup.get('NMTOKEN1API','')
                **self.get_token('key')
            }) 
        
        super(spirit, self, ).__init__()
        
        print('Fim')
        
        
    #--------------------------------------------------------#
    #------------------ TRATAMENTO RESPONSE  ----------------#
    #--------------------------------------------------------#
    
    def response_code_200(self, req) :
        return super().response_code_201(req)
        
        
    #--------------------------------------------------------#
    #------------------- TRATAMENTO BEFORESEND --------------#
    #--------------------------------------------------------#
    
    def beforeSend_productStock(self, data) :
        #pass
        if self.current_data['request_method'] == 'PUT' :
            del data['status']
            
        if not data['options']:
            del data['options']
            
        return data
            
        
    def beforeSend_taxClassForm(self, data):
        if self.current_data['request_method'] == 'POST':
            del data['tax_class_id']
        
        return data
        
    
    def beforeSend_taxRateForm(self, data):
        if self.current_data['request_method'] == 'POST':
            del data['tax_rate_id']
        else :
            data['tax_rate_id'] = int(data.get('tax_rate_id',0))
            
            
        
        
        return data
        
    
    #--------------------------------------------------------#
    #------------------- RELACIONA ID FUNC HEADER -----------#
    #--------------------------------------------------------#
    
    def custom_control_id(self, response) :
        
        res = self.tryJson(response) or {}
        
        if 'product' in res :
            return res['product']
        else:
            return ''
                
                
            
    def custom_control_id_taxClassForm(self, response) :
        return response.text
        
    
    def custom_control_id_taxRateForm(self, response) :
        return response.text
        
        
    
    
    
    #--------------------------------------------------------#
    #--------------- TRATAMENTO FILTROS DE ROTA -------------#
    #--------------------------------------------------------#
    def rote_filter_getCustomers(self):
        
        return  self.mountRouteParams(
            {
                #    "date_added" : alterado_apos
                    "approved"    : "0"
                ,   "sort"        : "ASC"
                ,   "status"      : "1"
            }
        )
        
    
    def rote_filter_orders(self):
        #from datetime import datetime
        
        
        sql =  """
            SELECT 
                DTULTIMAALTERACAO 
            FROM 
                TBRELACIONAID
            WHERE 
                1=1 
            AND NMTABELA = '{table}'
            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(
            {
                #    "date_start" : alterado_apos
                #    "date_end"   : datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                #    "limit"      : 100
                
                    "order_integrated"   : '0'
                ,   "order_status_id"    : '21'
                ,   "sort"               : 'ASC'
                
                #"order_id": 462
            }
        )
    
    #--------------------------------------------------------#
    #------------------ TRATAMENTO DATA PEDIDO --------------#
    #--------------------------------------------------------#
    def dateLastChanges(self):
        return self.current_order['date_modified']
        
    """
    ....###....########.########.########.########......######...########.########
    ...##.##...##..........##....##.......##.....##....##....##..##..........##...
    ..##...##..##..........##....##.......##.....##....##........##..........##...
    .##.....##.######......##....######...########.....##...####.######......##...
    .#########.##..........##....##.......##...##......##....##..##..........##...
    .##.....##.##..........##....##.......##....##.....##....##..##..........##...
    .##.....##.##..........##....########.##.....##.....######...########....##...
    """
    def afterGet_orders(self, data) :
        if data and data.get('success') :
            return data.get('orders')
        else : return []
        
        
    def afterGet_getCustomers(self, data) :
        return data.get('customers')
    #--------------------------------------------------------#
    #--------------- TRATAMENTO PEDIDO/ITEMS- ---------------#
    #--------------------------------------------------------#
    
    
    def get_order_items(self, order) :
        return [ self.extractValues(item, "itenscarrinho_fields") for item in order['products']]
        
    
    def get_order_data(self, order) :
        return [ self.extractValues(order, 'pedido_fields') ]
        
        

    #--------------------------------------------------------#
    #--------------- TRATAMENTO ITEMS/PEDIDO ----------------#
    #--------------------------------------------------------#
        
    
    def tipo_pessoa(self, data):
        tipo_pessoa = self.only_numbers(data)
        return "J" if len(tipo_pessoa) > 11 else "F"
        
    
    def order_total(self, data, props) :
        ref = props.get('ref')

        # ** Descomentar quando liberar desc_
        if ref == "descontos":
            total_discount = 0

            for order in data:
                if float(order['value']) < 0:
                    total_discount += float(order['value'])

            return total_discount
        
        else:
            data_filtered = list(filter(lambda item: item['code'] == ref, data))
            
            if data_filtered:
                return data_filtered[0]['value'] 
            else : 
                return '0'
        
    
    def shipping_code(self, data):
        """
            Tratamento de dados frete relacionado a empresa esj empresa 1 filial 1
        """
        #metodo, transportadora = data.split(".")
        
        if 'pickup' in data :
            return '9'
        else :
            return '1'
            
        
        
        
    def shipping_method(self, data):

        if data == "":
            return ''
        """
            Tratamento de dados transportadora relacionado a empresa esj empresa 1 filial 1
        """
        #metodo, transportadora = data.split(".")
        """ if 'pickup' in data :
            return 'T00100'
        elif 'free' in data:
            pass
            
        elif 'frenet' in data: """
        metodo, transportadora = data.split(".")
        """ transportadora_dict = {
            'correios':'T00021',
            '03220':'T00021',
        } """
        return self.shipping_map().get(metodo, {}).get(transportadora.lower(),  {}).get(self.nmlkgrupo.lower(), '')
            
    
    def shipping_map(self):
        return {
            "free":{
                "free":{"esj":"T00024","tratoraco":""}
            },
            "pickup":{
                "pickup":{"esj":"T00023","tratoraco":""}
            },
            "frenet":{
                    "03085":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (03085) NOVO
                ,   "04596":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (04596) NOVO
                ,   "04510":{ "esj":"T00022","tratoraco":""} #  PAC sem contrato (04510) NOVO
                ,   "04669":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (04669) NOVO
                ,   "04677":{ "esj":"T00022","tratoraco":""} #  PAC com contrato reverso (04677) NOVO
                ,   "41106":{ "esj":"T00022","tratoraco":""} #  PAC sem contrato (41106) Descontinuado
                ,   "41211":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (41211)
                ,   "41068":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (41068)
                ,   "04693":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (04693)
                ,   "03298":{ "esj":"T00022","tratoraco":""} #  PAC com contrato (03298)
                ,   "03050":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (03050) NOVO
                ,   "04556":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (04556)
                ,   "04553":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (04553) NOVO
                ,   "04014":{ "esj":"T00022","tratoraco":""} #  SEDEX sem contrato (04014) NOVO
                ,   "04162":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (04162) NOVO
                ,   "04170":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato reverso (04170) NOVO
                ,   "40010":{ "esj":"T00022","tratoraco":""} #  SEDEX sem contrato (40010) Descontinuado
                ,   "40096":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (40096)
                ,   "40436":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (40436)
                ,   "40444":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (40444)
                ,   "40568":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (40568)
                ,   "40606":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (40606)
                ,   "04138":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (04138)
                ,   "04537":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato grandes formatos (04537)
                ,   "04618":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato grandes formatos (04618)
                ,   "03220":{ "esj":"T00022","tratoraco":""} #  SEDEX com contrato (03220)
                ,   "40045":{ "esj":"T00022","tratoraco":""} #  SEDEX a Cobrar, sem contrato (40045)
                ,   "40126":{ "esj":"T00022","tratoraco":""} #  SEDEX a Cobrar, com contrato (40126)
                ,   "40215":{ "esj":"T00022","tratoraco":""} #  SEDEX 10, sem contrato (40215)
                ,   "03158":{ "esj":"T00022","tratoraco":""} #  SEDEX 10 com contrato (03158)
                ,   "40290":{ "esj":"T00022","tratoraco":""} #  SEDEX Hoje, sem contrato (40290)
                ,   "03204":{ "esj":"T00022","tratoraco":""} #  SEDEX HOJE com contrato (03204)
                ,   "40169":{ "esj":"T00022","tratoraco":""} #  SEDEX 12 com contrato (40169)
                ,   "03140":{ "esj":"T00022","tratoraco":""} #  SEDEX 12 com contrato (03140)
                ,   "04227":{ "esj":"T00022","tratoraco":""} #  MINI com contrato (04227)
                ,   "free":{ "esj":"T00024","tratoraco":""}  #  MINI com contrato (04227)
                ,   "owne":{ "esj":"T00024","tratoraco":""}  # Entrega Própria Motoboy - Em média 1 dia(s) após a postagem
                
            }
        }
    
    
    
    
    
    
    
    def get_cond_pgto(self):
        bandeira = self.current_order.get('bandeira','')
        parcela  = self.current_order.get('parcela', '')
        parcelas = '' if not parcela else f' {parcela}X'#.format(parcela)
        desc_pagamento = f"{bandeira}{parcelas}"#.format(bandeira, parcelas)
        
        result =  self.getDb().simple_select(
                fields  =["CDCONDPGTO"]
            ,   table   ="TBCONDPGTO"
            ,   where   =[f"DSCONDPGTO='{desc_pagamento}'"],
                onlyFirst=True
        )
        
        return result.get('CDCONDPGTO', '0')
        
        
    # Apenas para recuperar o id externo do cliente
    """ def customer_data(self, data) :
        data['IDCLIENTEEXTERNO'] = re.sub(
            r'[^\d]','',
            self.current_order.get(
                    'cpf',
                    self.current_order.get('cnpj','') 
                )
            )
        return data """
        
    def only_numbers(self, data):
        return  re.sub(r'[^\d]','',data)
    
    
    def afterSend_orderUpdate(self, data) :
        
        status = self.getDb().simple_select(
            table="TBSTATUS",
            fields=["CDSTATUS"],
            where=["NMAPI='spirit'",f"CDSTATUSEXTERNO='{data.get('order_status_id','')}'"],
            onlyFirst=True
        )
        delete = True
        if status and status.get('CDSTATUS',False) == 1 :
            res = self.spirit_request.doRequest(**{
                "rote": "setOrderIntegrated",
                "method": "POST",
                "json": {"order_id":data.get('order_id', None), 'order_integrated': 1} #json.dumps()
            })
            
            delete = res.status_code == 200
            
        if(delete):
            self.getDb().delete(
                "TBPEDIDOSSTATUS"
            ,   [f"IDTBPEDIDOSSTATUS={self.current_data['softdib_id']}"]
        )
            
        
    def beforeSend_orderUpdate(self, data):
        print(data)
        
        
        
    #--------------------------------------------------------#
    #-----------------TRATAMENTO DOS CUSTOM REPLACEMENT -----#
    #--------------------------------------------------------#
    
    def get_customer_group_id(self, data) -> str:
        values = data.split(",")
        if data:
            return json.dumps([ { 'customer_group_id': int(value) } for value in values ])
            
        return "[]"
    
    
    def get_geo_zone(self, code:str='') -> dict :
        """Recupera os dados de regiao cadastrado na spirit
        Args:
            filter_by (code): Codigo da região
        """
        if not self.zone_file:
            zone_file = self.read_file(f"{self.root_dir}/{self.apiName}/geoZone.json" );
            self.zone_file = json.loads(zone_file)
            
            
        return filter(lambda zone: zone.get('code', '') == code, self.zone_file)
            
        
        
        
        
    def get_geo_zone_id(self, uf):
        zone = list(self.get_geo_zone(uf))
        if zone:
            return zone[0].get('geo_zone_id')
            
        
        return uf
        
    def mount_images(self, images) :
        
        if images :
            images = images.split("|")
            
            """ data =  self.getDb().simple_select(
                    fields  =["NMIMAGEM","CDPRODUTO","VLSEQUENCIA"]
                ,   table   ="TBPRODUTOIMAGEM"
                ,   where   = [f"IDTBPRODUTOIMAGEM IN ({','.join( id.split(';')[0] for id in ids )})"]
            )
            
            """
            
            
            return json.dumps([{
                    "name": f"{self.slugify(self.current_data.get('name'))}-{index}.png",
                    "base64": img.replace('data:image/png;base64,',''),
                    "sort_order": index + 1,
                    "conf_pdt": "P" if index == 0 else "A"
                }
                
                for index,img in enumerate(images)
                
            ] )
            
            
            
            
        else: return []
        
        
        
    def order_customer_group_id(self, data):
        # 8 - consumidor final | 11 - Revendedor | 12 DIFAL menos parana
        
        tab_precos = self.tabprecoxgrupocliente()
        
        return tab_precos.get(data,"")
    
    def mount_prices(self, data):
        """Tratamento para precos 
        """
        prices = []
        
        if data:
            #if (self.nmlkgrupo.lower() == "tratoraco") :
            # relaca entre codigo dib e spirit
            
            
            ##_list = data.split("&")
            
            
            ##prices = f"&{data}"
            # ! Criar em cada interface da empresa a relação entre um grupo e o cliente
            for group, tabela in self.tabprecoxgrupocliente().items():
                price = self.get_cookie(tabela, data)
                if(price):
                    prices += [{
                        "customer_group_id": group,
                        "quantity": 0,
                        "priority": 0,
                        "price": float(price),
                    }]
            
        return json.dumps(prices)
        
        
    def get_cookie(self, name, data) :
        
        match = re.findall(rf'{name}=([^&]+)', data)
        if match:
            return match[0]
        
        
    
    
    
    def slugify(self, text):
        non_url_safe = ['"', '#', '$', '%', '&', '+',
                    ',', '/', ':', ';', '=', '?',
                    '@', '[', '\\', ']', '^', '`',
                    '{', '|', '}', '~', "'"]
        
        translate_table = {ord(char): u'' for char in non_url_safe}
        text = text.translate(translate_table)
        text = u'_'.join(text.split())
        return text
        
    #--------------------------------------------------------#
    #-----------------TRATAMENTO DOS CUSTOM------------------#
    #--------------------------------------------------------#
    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 product_discount(self, data):
        return """
            (
                
                SELECT
                    GROUP_CONCAT(
                        CONCAT(
                            TBTABPRECOPRODUTO.CDTABELA,
                            "=",
                            TBTABPRECOPRODUTO.VLPRODUTO
                        ) SEPARATOR '&'
                    ) AS tmp
                FROM
                    TBTABPRECOPRODUTO
                WHERE
                    TBTABPRECOPRODUTO.CDPRODUTO = TBPRODUTO.CDPRODUTO
                    
                
                
            )
        """
        
    
    def products_images(self, data):
        return """ 
        (SELECT
            DISTINCT (
                SELECT
                    GROUP_CONCAT(TBPRODUTOIMAGEM.NMIMAGEM SEPARATOR '|' ) AS tmp
                FROM
                    TBPRODUTOIMAGEM
                WHERE
                    TBPRODUTOIMAGEM.CDPRODUTO = TBPRODUTO.CDPRODUTO
            )
        )
        """
        
    
    
        
        
    
    
    """
        ABSTRACT CLASSES
    """
    def tabprecoxgrupocliente(self):
        exit("Method nao encontrado")
        
    def payment_code(self,data):
        exit("Method nao encontrado")
        
    def product_ipi(self,data):
        exit("Method nao encontrado")
    
    
    def __del__(self):
        self.createLog("999","Final da exportacao")
        
        
        
        
        
        
        
        
        
        
        
    
    