const database = require('../config/database')
const authToken = require('../config/authToken')
const response = require("../constants/response");
const logger = require('../services/loggerService');
const paginationRecords = require("../helpers/paginationRecords")
const { credenciaisFilteres } = require('../helpers/filterResponseSQL');

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

      logger("SERVIDOR:getCredencial").debug("Á buscar os dados");;
      const credencial = await database('crendecias_api')
      .join("clientes","clientes.numero_entidade","=","crendecias_api.entidade")
      .orderBy('id_credencial','DESC')

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

      logger("SERVIDOR:getCredencial").debug(`Á buscar os dados filtrados`);
      const credencialLimite = await database('crendecias_api')
      .join("clientes","clientes.numero_entidade","=","crendecias_api.entidade")
      .whereLike("entidade",`%${entidade}%`)
      .limit(registros.limite)
      .offset(registros.count)
      .orderBy("id_credencial", "DESC");

      const filtered = credenciaisFilteres(credencialLimite)

      registros.total_apresentados = credencialLimite.length
      registros.entidade = entidade
      
      logger("SERVIDOR:getCredencial").info("Respondeu a requisição");
      const rs = response("sucesso", 200, filtered, 'json', {registros})
      return rs;

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

module.exports.getCredencialId = async function(id_credencial) {
  try {

      logger("SERVIDOR:getCredencialId").debug("Á buscar os dados");
      const credencial = await database('crendecias_api')
      .join("clientes","clientes.numero_entidade","=","crendecias_api.entidade")
      .where({id_credencial})
      .orderBy('id_credencial','DESC')

      const [filtered] = credenciaisFilteres(credencial)

      logger("SERVIDOR:getCredencialId").info("Respondeu a requisição");
      const rs = response("sucesso", 200, filtered || {})
      return rs;

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

module.exports.getCredencialEntidade = async function(entidade) {
  try {

      logger("SERVIDOR:getCredencialEntidade").debug("Á buscar os dados");
      const verifivarPagamentoTempoReal = await database('configuracoes').where({cliente_entidade: entidade})        

      if((verifivarPagamentoTempoReal[0]?.servico_pagamento_por_sector == "false") && (verifivarPagamentoTempoReal[0]?.servico_gpo == "false")){ 
        logger("SERVIDOR:getCredencialEntidade").info("Serviço de pagamento por sector invativo")
        const rs = response("erro", 423, "Serviço de pagamento por sector invativo");
        return rs  
      }

      logger("SERVIDOR:getCredencialEntidade").debug("Á buscar os dados");
      const credencial = await database('crendecias_api')
      .join("clientes","clientes.numero_entidade","=","crendecias_api.entidade")
      .where({entidade})
      .orderBy('id_credencial','DESC')

      const [filtered] = credenciaisFilteres(credencial)

      logger("SERVIDOR:getCredencialEntidade").info("Respondeu a requisição");
      const rs = response("sucesso", 200, filtered || {})
      return rs;

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

module.exports.postCredencial = async function(dados, req) {
  try {

    logger("SERVIDOR:postCredencial").debug("Á buscar as configurações do cliente");
    const verifivarPagamentoTempoReal = await database('configuracoes').where({cliente_entidade: dados.entidade})        

    if((verifivarPagamentoTempoReal[0]?.servico_pagamento_por_sector == "false") && (verifivarPagamentoTempoReal[0]?.servico_gpo == "false")){
      logger("SERVIDOR:postCredencial").info("Serviço de pagamento inactivo")
      const rs = response("erro", 423, "Serviço de pagamento inactivo");
      return rs   
    }

    logger("SERVIDOR:postCredencial").debug("Á buscar os dados do cliente");
    const resultEnt  = await database('clientes').where({numero_entidade: dados.entidade})
    
    if(resultEnt.length < 1 ){
      logger("SERVIDOR:postCredencial").info("Impossivel gerar o token para uma entidade inexistente!")
      const rs = response("erro", 406, "Impossivel gerar o token para uma entidade inexistente!");
      return rs 
    }
    
    if(dados.secret_api.length < 25){
      logger("SERVIDOR:postCredencial").info("Chave de segredo do token invalido! Deve ter 25 ou mais caracteres")
      const rs = response("erro", 412, "Chave de segredo do token invalido! Deve ter 25 ou mais caracteres");
      return rs 
    }
    
    logger("SERVIDOR:postCredencial").debug("Á buscar os dados de existencia de tokens");
    const existsToken = await database('crendecias_api').where({entidade: dados.entidade})
    const quando_actualizado = new Date().toISOString().replace('T',' ').substr(0,19)
    
    logger("SERVIDOR:postCredencial").debug("Á gerar o token");
    const token_api = authToken.generateToken({...resultEnt[0], secret_api:dados.secret_api, quando_actualizado})
    
    
    if(existsToken.length > 0){
      
      logger("SERVIDOR:postCredencial").debug("Á actualizar os dados");
      await database('crendecias_api').where({id_credencial: existsToken[0].id_credencial}).update({secret_api:dados.secret_api, quando_actualizado,token_api})

      logger("SERVIDOR:postCredencial").info("Token gerado com sucesso ");
      const rs = response("sucesso", 202, "Token gerado com sucesso ", 'json', {
        webhook: {id_evento: 12, entidade: dados.entidade, info:{ ...dados }},
        logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "PATCH" , tabela: "CREDENCIAS_API", informacao: dados, entidade: dados.entidade},
        token: token_api
      })

      return rs;
      
    }
    
    logger("SERVIDOR:postCredencial").debug("Á gravar os dados ");
    await database('crendecias_api').insert({...dados,token_api})

    logger("SERVIDOR:postCredencial").info("Token gerado com sucesso ");
    const rs = response("sucesso", 201, "Token gerado com sucesso ", 'json', {
      webhook: {id_evento: 11, entidade: dados.entidade, info:{ ...dados }},
      logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "POST" , tabela: "CREDENCIAS_API", informacao: dados, entidade: dados.entidade},
      token: token_api
    })
      
    return rs;
    
  } catch (error) {
      console.log(error);
      logger("SERVIDOR:postCredencial").error(`Erro a cadastrar ${error.message}`)
      const rs = response("erro", 400, 'Algo aconteceu. Tente de novo');
      return rs
  }
    
}

module.exports.patchCredencialSecretKey = async function(entidade, dados, req) {
  try {  

      logger("SERVIDOR:patchCredencialSecretKey").debug("Á buscar as configurações do cliente");
      const verifivarPagamentoTempoReal = await database('configuracoes').where({cliente_entidade: entidade})        

      if((verifivarPagamentoTempoReal[0]?.servico_pagamento_por_sector == "false") && (verifivarPagamentoTempoReal[0]?.servico_gpo == "false")){
        logger("SERVIDOR:patchCredencialSecretKey").info("Serviço de pagamento inactivo")
        const rs = response("erro", 423, "Serviço de pagamento inactivo");
        return rs     
      }

      logger("SERVIDOR:patchCredencialSecretKey").debug("Á buscar os dados do cliente");
      const cliente  = await database('clientes').where({numero_entidade: entidade})
      
      if(cliente.length < 1 ){
        logger("SERVIDOR:patchCredencialSecretKey").info("Impossivel gerar o token para uma entidade inexistente!")
        const rs = response("erro", 406, "Impossivel gravar a chave para uma entidade inexistente!");
        return rs 
      }

      const quando_actualizado = new Date().toISOString().replace('T',' ').substr(0,19)
      
      logger("SERVIDOR:patchCredencialSecretKey").debug("Á buscar os dados de existencia de tokens");
      const resultEnt  = await database('crendecias_api').where({entidade})
      
      if(resultEnt.length < 1 ){
        logger("SERVIDOR:patchCredencialSecretKey").info("Impossivel actualizar o token chave de segredo invalida!")
        const rs = response("erro", 409, "Impossivel actualizar o token chave de segredo invalida!");
        return rs
      }
      
      if(dados.secret_api.length < 25){
        logger("SERVIDOR:patchCredencialSecretKey").info("Chave de segredo do token invalido! Deve ter 25 ou mais caracteres")
        const rs = response("erro", 412, "Chave de segredo do token invalido! Deve ter 25 ou mais caracteres");
        return rs
      }

      logger("SERVIDOR:patchCredencialSecretKey").debug("Á actualizar os dados");
      await database('crendecias_api').where({id_credencial}).update({...dados,quando_actualizado})
      
      logger("SERVIDOR:patchCredencialSecretKey").info("Chave de segredo actualizada com sucesso feita com sucesso");
      const rs = response("sucesso", 202, "Chave de segredo actualizada com sucesso feita com sucesso", 'json', {
        webhook: {id_evento: 14, entidade, info:{ ...dados }},
        logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "PATCH" , tabela: "CREDENCIAS_API", informacao: {...dados, entidade}, entidade}
      })

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

module.exports.patchCredencial = async function(entidade, dados, req) {
  try {  

      logger("SERVIDOR:patchCredencial").debug("Á buscar as configurações do cliente");
      const verifivarPagamentoTempoReal = await database('configuracoes').where({cliente_entidade: entidade})        

      if((verifivarPagamentoTempoReal[0]?.servico_pagamento_por_sector == "false") && (verifivarPagamentoTempoReal[0]?.servico_gpo == "false")){
        logger("SERVIDOR:patchCredencial").info("Serviço de pagamento inactivo")
        const rs = response("erro", 423, "Serviço de pagamento inactivo");
        return rs     
      }

      logger("SERVIDOR:patchCredencial").debug("Á buscar os dados do cliente");
      const cliente  = await database('clientes').where({numero_entidade: entidade})
      
      if(cliente.length < 1 ){
        logger("SERVIDOR:patchCredencial").info("Impossivel gerar o token para uma entidade inexistente!")
        const rs = response("erro", 406, "Impossivel gravar a chave para uma entidade inexistente!");
        return rs 
      }

      const quando_actualizado = new Date().toISOString().replace('T',' ').substr(0,19)
      
      logger("SERVIDOR:patchCredencial").debug("Á verificar existencia");
      const resultEnt  = await database('crendecias_api').where({secret_api: dados.secret_api}).andWhere({entidade})
      
      if(resultEnt.length < 1 ){
        logger("SERVIDOR:patchCredencial").info("Impossivel actualizar o token chave de segredo invalida!")
        const rs = response("erro", 409, "Impossivel actualizar o token chave de segredo invalida!");
        return rs
      }
      
      logger("SERVIDOR:patchCredencial").debug("Á gerar o token");
      const token_api = authToken.generateToken(resultEnt[0])

      logger("SERVIDOR:patchCredencial").debug("Á actualizar os dados");
      await database('crendecias_api').where({id_credencial}).update({...dados,quando_actualizado,token_api})

      logger("SERVIDOR:patchCredencial").info("Token actualizado com sucesso feita com sucesso");
      const rs = response("sucesso", 202, "Token actualizado com sucesso feita com sucesso", 'json', {
        webhook: {id_evento: 12, entidade, info:{ ...dados }},
        token: token_api,
        logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "PATCH" , tabela: "CREDENCIAS_API", informacao: {...dados, entidade}, entidade}
      })

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

module.exports.deleteCredencial = async function(entidade, req) {
  try {  
    
      logger("SERVIDOR:deleteCredencial").debug("Á buscar as configurações do cliente");
      const verifivarPagamentoTempoReal = await database('configuracoes').where({cliente_entidade: entidade})

      if((verifivarPagamentoTempoReal[0]?.servico_pagamento_por_sector == "false") && (verifivarPagamentoTempoReal[0]?.servico_gpo == "false")){
        logger("SERVIDOR:deleteCredencial").info("Serviço de pagamento inactivo")
        const rs = response("erro", 423, "Serviço de pagamento inactivo");
        return rs     
      }

      logger("SERVIDOR:deleteCredencial").debug("Á buscar os dados do cliente");
      const cliente  = await database('clientes').where({numero_entidade: entidade})
      
      if(cliente.length < 1 ){
        logger("SERVIDOR:deleteCredencial").info("Impossivel gerar o token para uma entidade inexistente!")
        const rs = response("erro", 406, "Impossivel gravar a chave para uma entidade inexistente!");
        return rs 
      }

      logger("SERVIDOR:deleteCredencial").debug("Á deletar os dados");
      await database('crendecias_api').where({entidade}).del()

      logger("SERVIDOR:deleteCredencial").info("Parametrização excluida feita com sucesso");
      const rs = response("sucesso", 202, "Parametrização excluida feita com sucesso", 'json', {
        webhook: {id_evento: 15, entidade, info:{}},
        token: token_api,
        logs: {ip: req.ip, verbo_rota_API: req.method, rota_API: req.originalUrl, tipo: "DELETE" , tabela: "CREDENCIAS_API", informacao: {entidade}, entidade}
      })

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