const database = require('../config/database')
const fs = require('fs')
const path = require('path');
const pagination = require("../constants/pagination");
const response = require("../constants/response");
const logger = require('../services/loggerService');
const {relatoriosFilteres} = require("../helpers/filterResponseSQL")
const paginationRecords = require("../helpers/paginationRecords")


module.exports.getRelatorios = async function(pagina, limite, total_registros, nome_empresa, email, entidade) {
     
     try{

        const relatorios = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .limit(total_registros || pagination.total_limite)
        .orderBy('id_relatorio','desc')


        const {registros} = paginationRecords(relatorios, pagina, limite)

        const relatoriosLimite = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .limit(registros.limite)
        .offset(registros.count)
        .orderBy('id_relatorio','desc')
        
        const filtered = relatoriosFilteres(relatoriosLimite)
        registros.total_apresentados = relatoriosLimite.length
        registros.nome_empresa = nome_empresa
        registros.email = email
        registros.entidade = entidade
  
        delete registros.count
  
        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 200, filtered, "json", { registros });
        return rs
      
      
     } catch (error) {
        console.log(error)
        logger("SERVIDOR:Clientes").error(`Erro ao buscar clientes ${error.message}`)
        const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
        return rs
    }
    
}

module.exports.getRelatoriosId = async function(id_relatorio) { 
     
     try{
        const relatorios = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade") 
        .where({id_relatorio})
        .orderBy('id_relatorio','desc')

        const filtered = relatoriosFilteres(relatorios)
        
        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 200, filtered);
        return rs   
      
      
     } catch (error) {
        console.log(error)
        logger("SERVIDOR:Clientes").error(`Erro ao buscar clientes ${error.message}`)
        const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
        return rs
    }
    
}

module.exports.getRelatoriosEntidade = async function(pagina, limite, total_registros, entidade) {
     
     try{

        const relatorios = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .where({entidade})
        .limit(total_registros || pagination.total_limite)
        .orderBy('id_relatorio','desc')

        const {registros} = paginationRecords(relatorios, pagina, limite)

        const relatoriosLimite = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .where({entidade})
        .limit(registros.limite)
        .offset(registros.count)
        .orderBy('id_relatorio','desc')
        
        const filtered = relatoriosFilteres(relatoriosLimite)

        registros.total_apresentados = relatoriosLimite.length
        registros.entidade = entidade
        
        delete registros.count
  
        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 200, filtered, "json", { registros });
        return rs
      
     } catch (error) {
        console.log(error)
        logger("SERVIDOR:Clientes").error(`Erro ao buscar clientes ${error.message}`)
        const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
        return rs
    }
    
}

module.exports.getRelatoriosEntidadeTipo = async function(pagina, limite, total_registros, entidade, para) {
     
     try{

        const relatorios = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .where({entidade})
        .andWhere({para})
        .limit(total_registros || pagination.total_limite)
        .orderBy('id_relatorio','desc')

        const {registros} = paginationRecords(relatorios, pagina, limite)

        const relatoriosLimite = await database('relatorios')
        .join("clientes","clientes.numero_entidade","=","relatorios.entidade")
        .where({entidade})
        .andWhere({para})
        .limit(registros.limite)
        .offset(registros.count)
        .orderBy('id_relatorio','desc')
        
        const filtered = relatoriosFilteres(relatoriosLimite)

        registros.total_apresentados = relatoriosLimite.length
        registros.entidade = entidade
        registros.para = para
        
        delete registros.count
  
        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 200, filtered, "json", { registros });
        return rs
      
     } catch (error) {
        console.log(error)
        logger("SERVIDOR:Clientes").error(`Erro ao buscar clientes ${error.message}`)
        const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
        return rs
    }
    
}

module.exports.postRelatorios = async function({entidade, tipo, campos}) {

    
    try {

      const filename = new Date().toISOString().split('Z')[0].replaceAll('-','').replaceAll('T','').replaceAll(':','').replaceAll('.','')+'.xlsx'
      let gerou = false;

      if(tipo == "Referencias"){
        logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
        const produtos_clientes = await database("produtos_clientes")
        .join("tipo_produto_cliente", "tipo_produto_cliente.id_tipo_produto_clientes", "=", "produtos_clientes.cliente_tipo_produto")
        .join("clientes", "clientes.id_clientes", "=", "tipo_produto_cliente.cliente")
        .join("tipo_produto", "tipo_produto.id_tipo_produto", "=", "tipo_produto_cliente.tipo_registo")
        .orderBy("id_produto", "DESC")
        .where({ numero_entidade: entidade});

        if(produtos_clientes[0].id_tipo_produto == 1){

          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          const referencias =  await database('referencias')
          .select('num_referencia as REFERÊNCIA',
          'data_limite_pagamento as DATA LIMETE DE PAGAMENTO',
          'estado_atm as ESTADO',
          'criada_r as CRIAÇÃO',
          'opcional_1 as Valor opcional 1',
          'opcional_2 as Valor opcional 2',
          'opcional_3 as Valor opcional 3')
          .where({entidade_cliente: entidade})
          .andWhereILike('num_referencia', `%${campos.referencia}%`)
          .andWhereILike('data_limite_pagamento', `%${campos.limite_pagamento}%`)
          .andWhereILike('estado_atm', `%${campos.estado}%`)
          .andWhereBetween("criada_r", [campos.data_inicio, campos.data_final])
          .orderBy('id_referencia','desc')
          
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          referencias.map(function(fn){
                fn["CRIAÇÃO"] = new Date(fn["CRIAÇÃO"]).toLocaleString()
                fn["DATA LIMETE DE PAGAMENTO"] = new Date(fn["DATA LIMETE DE PAGAMENTO"]).toLocaleDateString()
                //fn["VALOR OPCIONAL 1"] = String(fn["VALOR OPCIONAL 1"]).split('=')[1]
                //fn["VALOR OPCIONAL 2"] = String(fn["VALOR OPCIONAL 2"]).split('=')[1]
                //fn["VALOR OPCIONAL 3"] = String(fn["VALOR OPCIONAL 3"]).split('=')[1]
  
                return fn
          })
  
          if(referencias.length) {
            gerou = true
            logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
            await database('relatorios').insert({para: tipo, file_gerado: filename, entidade});
          }
          
          logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
          const rs = response("sucesso", 201, {tipo, referencias, filename});
          return rs
          

        }

        if(produtos_clientes[0].id_tipo_produto == 3){
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          const referencias =  await database('referencias')
          .select('num_referencia as REFERÊNCIA',
          'data_inicio_de_pagamento as DATA INICIO DE PAGAMENTO',
          'data_limite_pagamento as DATA LIMETE DE PAGAMENTO',
          'estado_atm as ESTADO',
          'montante_minimo as MONTANTE MINIMO',
          'montante_maximo as MONTANTE MAXIMO',
          'numero_de_linhas as NUMERO DE LINHAS PARA O TALÃO',
          'textos_para_talao as TEXTO Á APRESENTAR AO TALÃO',
          'criada_r as CRIAÇÃO',
          'nome_identificacao as GRUPO DE AFILIADOS',
          'opcional_1 as VALOR OPCIONAL 1',
          'opcional_2 as VALOR OPCIONAL 2',
          'opcional_3 as VALOR OPCIONAL 3')
          .join("afiliados","afiliados.id_afiliado","=","referencias.gerado_por_afiliado")
          .join("identificacao_afiliados","identificacao_afiliados.id_identificacao_afiliados","=","afiliados.grupo_identificacao")
          .where({entidade_cliente: entidade})
          .andWhereILike('num_referencia', `%${campos.num_referencia}%`)
          .andWhereILike('data_limite_pagamento', `%${campos.data_limite_pagamento}%`)
          .andWhereILike('estado_atm', `%${campos.estado_atm}%`)
          .andWhereILike('grupo_identificacao', `%${campos.grupo_identificacao}%`)
          .andWhereBetween("criada_r", [campos.dia_inicio, campos.dia_final])
          .orderBy('id_referencia','desc')
  
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          referencias.map(function(fn){
                fn["CRIAÇÃO"] = new Date(fn["CRIAÇÃO"]).toLocaleString()
                fn["DATA INICIO DE PAGAMENTO"] = new Date(fn["DATA INICIO DE PAGAMENTO"]).toLocaleDateString()
                fn["DATA LIMETE DE PAGAMENTO"] = new Date(fn["DATA LIMETE DE PAGAMENTO"]).toLocaleDateString()
                fn["VALOR OPCIONAL 1"] = String(fn["VALOR OPCIONAL 1"]).split('=')[1]
                fn["VALOR OPCIONAL 2"] = String(fn["VALOR OPCIONAL 2"]).split('=')[1]
                fn["VALOR OPCIONAL 3"] = String(fn["VALOR OPCIONAL 3"]).split('=')[1]
  
                return fn
          })
  
          if(referencias.length) {
            gerou = true
            logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
            await database('relatorios').insert({para: tipo, file_gerado: filename, entidade});
          }
          
          logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
          const rs = response("sucesso", 201, {tipo, referencias, filename});
          return rs

        }


      }

      if(tipo == "Pagamentos"){
        logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
        const pagamentos =  await database('pagamentos')
        .select('data_movimento as DATA DO MOVIMENTO', 
        'Identificacao_Log_EGR as IDENTIFICAÇAO LOG EGR',
        'numero_Log_EGR as NÚMERO LOG EGR',
        'montante_da_operacao as MONTANTE DA OPERAÇÃO',
        'referencia_do_servico as REFERÊNCIA',
        'localidade as LOCALIDADE',
        'tipo_de_Terminal AS TERMINAL USADO')
        .join("referencias","referencias.num_referencia","=","pagamentos.referencia_do_servico")
        .where({numero_entidade: entidade})
        .andWhereILike('referencia_do_servico', `%${campos.referencia}%`)
        .andWhereILike('montante_da_operacao', `%${campos.montante}%`)
        .andWhereILike('tarifa_aplicada_a_operacao', `%${campos.tarifa}%`)
        .andWhereILike('numero_Log_EGR', `%${campos.log_transacao}%`)
        .andWhereILike('tipo_de_Terminal', `%${campos.terminal}%`)
        .andWhereILike('Identificacao_Log_EGR', `%${campos.periodo}%`)
        .andWhereILike('hora_do_movimento', `%${campos.hora_transacao}%`)
        .andWhereILike('nib', `%${campos.nib}%`)
        .andWhereBetween("data_movimento", [campos.data_inicio, campos.data_final])
        .orderBy('id_pagamento','desc')

        logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
        const terminal = {
          A:'ATM',
          M:'MULTICAIXA EXPRESS',
          L:'INTERNET BANK'
        }
        pagamentos.map(function(fn){
          fn["DATA DO MOVIMENTO"] = fn["DATA DO MOVIMENTO"] ? new Date(fn["DATA DO MOVIMENTO"]).toLocaleDateString() : "AGUARDAR CONCILIAÇÃO"
          fn["MONTANTE DA OPERAÇÃO"] = Intl.NumberFormat("PT-br").format(Number(fn["MONTANTE DA OPERAÇÃO"]))
          fn["TERMINAL USADO"] = terminal[fn["TERMINAL USADO"]]
          //fn["VALOR OPCIONAL 1"] = String(fn["VALOR OPCIONAL 1"]).split('=')[1]
          //fn["VALOR OPCIONAL 2"] = String(fn["VALOR OPCIONAL 2"]).split('=')[1]
          //fn["VALOR OPCIONAL 3"] = String(fn["VALOR OPCIONAL 3"]).split('=')[1]

          return fn
        })

        if(pagamentos.length) {
          gerou = true
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          await database('relatorios').insert({para: tipo, file_gerado: filename, entidade});
        }
        
        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 201, {tipo, pagamentos, filename});
        return rs
      }

      if(tipo == "Periodos"){

        let periodos;

        if((campos.dia_inicio != "" ) && (campos.dia_final != "" )){
          
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          periodos =  await database('pagamentos')
          .select("data_movimento AS DATA DO PERIODO")
          .distinct("Identificacao_Log_EGR AS PERIODO CONTABILISTICO")
          .sum("montante_da_operacao AS MONTANTE AGREGADO")
          .count("id_pagamento AS QUANTIDADE")
          .where({numero_entidade: entidade})
          //.andWhereILike('MONTANTE AGREGADO', `%${campos.montante}%`)
          .andWhereILike('Identificacao_Log_EGR', `%${campos.periodo}%`)
          .andWhereBetween("data_movimento", [campos.data_inicio, campos.data_final])
          .groupBy(['Identificacao_Log_EGR',"data_movimento"])
          .orderBy('Identificacao_Log_EGR','desc')
        
        }else{

          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          periodos =  await database('pagamentos')
          .select("data_movimento AS DATA DO PERIODO")
          .distinct("Identificacao_Log_EGR AS PERIODO CONTABILISTICO")
          .sum("montante_da_operacao AS MONTANTE AGREGADO")
          .count("id_pagamento AS QUANTIDADE")
          .where({numero_entidade: entidade})
          .andWhereILike('montante_da_operacao', `%${campos.montante_da_operacao}%`)
          .andWhereILike('Identificacao_Log_EGR', `%${campos.Identificacao_Log_EGR}%`)
          .groupBy(['Identificacao_Log_EGR',"data_movimento"])
          .orderBy('Identificacao_Log_EGR','desc')

        }

        logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
        periodos.map(function(fn){
          fn["DATA DO PERIODO"] = fn["DATA DO PERIODO"] ? new Date(fn["DATA DO PERIODO"]).toLocaleDateString() : "AGUARDAR CONCILIAÇÃO"
          fn["MONTANTE AGREGADO"] = Intl.NumberFormat("PT-br").format(Number(fn["MONTANTE AGREGADO"]))

          return fn
        })

        if(periodos?.length) {
          gerou = true
          logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
          await database('relatorios').insert({para: tipo, file_gerado: filename, entidade});
        }

        logger("SERVIDOR:Clientes").info("Respondeu a solicitação")
        const rs = response("sucesso", 201, {tipo, periodos, filename});
        return rs
      }

      
  } catch (error) {
      console.log(error)
      logger("SERVIDOR:Clientes").error(`Erro ao buscar clientes ${error.message}`)
      const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
      return rs
  }
    
}

module.exports.deleteRelatorios = async function (id_relatorio, req) {
  try {

      logger("SERVIDOR:deleteRelatorios").debug("Buscar os afiliados no banco de dados");
      const file = await database("relatorios").where({ id_relatorio })

      if (file.length == 0) {
        logger("SERVIDOR:deleteRelatorios").info("arquivo não encontrado")
        const rs = response("erro", 409, "arquivo não encontrado");
        return rs
      } 

      const existsFile = fs.existsSync(path.join(__dirname, "../reports", file[0].file_gerado))
      if(existsFile){
        fs.unlinkSync(path.join(__dirname, "../reports", file[0].file_gerado));
      }
      
      await database("relatorios").where({ id_relatorio }).del();
      
      logger("SERVIDOR:deleteRelatorios").info("Arquivo excluido feita com sucesso");
      const rs = response("sucesso", 202, "Arquivo excluido feita com sucesso", 'json', {
        logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "DEFAULT" , tabela: "RELATORIOS", informacao: {id_relatorio, ...file[0]}}
      });

      return rs;

  } catch (error) {
      console.log(error)
      logger("SERVIDOR:deleteRelatorios").error(`Erro ao buscar clientes ${error.message}`)
      const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
      return rs
  }

};
