
// feito essa classe pois no fonte estava sendo repetido diversas vezes a mesma função com tudo igual e ainda alguns estavam errados...
// então fiz uma classe que pode ser usada em qualquer lugar do sistema, basta instanciar e chamar os métodos necessários.
// exemplo de uso:
// const epc = new EPC({ 
//                      barra: 'id input da barra', 
//                      quantidade: 'id input da quantidade', 
//                      deposito: 'id input do deposito', 
//                      codigoEPC: 'id input do codigoEPC', 
//                      integracaoEPC: '1', 
//                      callBackSaidaBarra: () => { /* sua função aqui */ }
//                    });

// botão para iniciar a leitura dos codigos EPC
// $('#btn-iniciar-epc').on('click', () => {
//   $('#btn-iniciar-epc').prop('disabled', true);
//   $('#btn-parar-epc').prop('disabled', false);
//   epc.iniciar()
// });

// botão para parar a leitura dos codigos EPC
// $('#btn-parar-epc').on('click', () => {
//   $('#btn-iniciar-epc').prop('disabled', false);
//   $('#btn-parar-epc').prop('disabled', true);
//   epc.parar()
// });

class EPC {
  constructor({ barra, quantidade, deposito, codigoEPC, idItem, integracaoEPC, callBackSaidaBarra, listaBarrasBipadasEPC, buttonEstorna, venda = false }) {
    this.barra = barra;
    this.quantidade = quantidade;
    this.deposito = deposito;
    this.codigoEPC = codigoEPC;
    this.idItem = idItem;
    this.integracaoEPC = integracaoEPC;
    this.callBackSaidaBarra = callBackSaidaBarra
    this.buttonEstorna = buttonEstorna
    this.epc = ''

    this.listaBarrasForamBipadasEPC = [];
    this.listaBarrasBipadasEPC = listaBarrasBipadasEPC ?? [];
    this.venda = venda;
  }

  // destructor() {
  //   listaBarrasBipadasEPC = this.listaBarrasBipadasEPC;
  // }

  async iniciar() {
    $.LoadingOverlay("show");
    try {
      if (!pegaChave(this.deposito)) {
        msgAlerta('Informe o depósito para iniciar a leitura RFID!');
        return false;
      }

      const response = await requisicao_ecf('POST', '/epc/inicia?', `INTEGRACAO=${this.integracaoEPC}`);
      if (!response || response.status !== 200) {
        msgAlerta('Erro ao iniciar a leitura RFID!');
        return false
      }

      return true
    } catch (error) {
      console.error('Erro ao iniciar a leitura RFID', error);
    } finally {
      $.LoadingOverlay("hide");
    }
  }

  async parar() {
    $.LoadingOverlay("show");
    try {
      const response = await requisicao_ecf('PUT', '/epc/para?', `INTEGRACAO=${this.integracaoEPC}`);
      if (!response || response.status !== 200) {
        msgAlerta('Erro ao parar a leitura RFID!');
        return false
      }
      await this.retornaCodigos();

      return true;
    } catch (error) {
      console.error('Erro ao parar a leitura RFID', error);
    } finally {
      $.LoadingOverlay("hide");
    }
  }

  async retornaCodigos(estorno = false, listaEPC) {
    try {
      const response = await requisicao_ecf('GET', '/epc/retorna?', `INTEGRACAO=${this.integracaoEPC}`);
      if (!response || response.status !== 200) msgAlerta('Erro ao retornar codigos da leitura RFID!');

      const data = await response.text();
      this.listaBarrasForamBipadasEPC = JSON.parse(data);

      // quando for testar interno com varias barras só adicionar no array todas que ele ira utilizar elas em vez de bipar uma por uma...
      // this.listaBarrasForamBipadasEPC = [
      // ]

      if (this.integracaoEPC === '2') {
        this.listaBarrasForamBipadasEPC = this.listaBarrasForamBipadasEPC.data.epcs;
      }

      if (this.listaBarrasForamBipadasEPC.length === 0) return msgAlerta('Nenhum código bipado!');

      if (!estorno && await this.barraJaEstaBipada()) estorno = true;

      if (this.venda) {
        await this.callBackSaidaBarra()
        return;
      }

      await this.retornaProdutos(estorno ? listaEPC : this.listaBarrasForamBipadasEPC, estorno);
    } catch (error) {
      console.error('Erro ao retornar codigos da leitura RFID', error);
    }
  }

  async estornaBarraBipadaEPC(sBarra) {
    try {
      this.listaBarrasBipadasEPC = [...this.listaBarrasBipadasEPC.filter(item => item.barra !== sBarra)];
    } catch (error) {
      console.error(error);
    }
  }

  async barraJaEstaBipada() {
    const repetidas = this.listaBarrasForamBipadasEPC.filter(barra => this.listaBarrasBipadasEPC.includes(barra));
    if (repetidas.length > 0) {
      this.listaBarrasForamBipadasEPC = this.listaBarrasForamBipadasEPC.filter(barra => !this.listaBarrasBipadasEPC.includes(barra));
      return await aguardaMsgAlerta(`RFID ${repetidas.join(', ')} já lido, o mesmo será estornado.`, async () => {
        await this.limpaBarras(repetidas);
        return true;
      });
    }
    return false;
  }

  async fetchDetalhesEPCs(listaEPCs = []) {
    if (listaEPCs.length === 0) return [];

    try {
      const listaFormatada = listaEPCs.map(epc => `'${epc}'`).join(',');

      const params = new URLSearchParams({
        DEPOSITO: pegaChave(this.deposito)
      });

      const response = await requisicao('POST', '/sisplan/epc/v1/detalhes?', params.toString(), listaFormatada);

      if (!response || response.status !== 200) msgAlerta('Erro ao buscar os detalhes dos EPC!');

      const dados = await response.json();
      return Array.isArray(dados) ? dados : [];

    } catch (error) {
      console.error('Erro ao buscar detalhes EPC:', error);
      msgErro('Erro ao consultar detalhes dos EPCs.');
      return [];
    }
  }


  async retornaProdutos(codigosEPC, estorno = false) {
    const detalhesEPCs = await this.fetchDetalhesEPCs(codigosEPC);

    const epcsPermitidos = detalhesEPCs.filter(e => e.PERMITE_MOVIMENTACAO === 'S');
    const epcsNegados = detalhesEPCs.filter(e => e.PERMITE_MOVIMENTACAO !== 'S');

    if (epcsPermitidos.length === 0) return;

    await this.bipa(epcsPermitidos, estorno);

    if (epcsNegados.length > 0) {
      msgAlerta(`Codigos: ${epcsNegados.map((dado) => `${dado.EPC},`)} não existem ou estão desativados na base de dados, faça a bipagem manual!`);
    }
  }

  async verificaSeTodosExistem(codigos, retornos) {
    const retornados = retornos.map(d => d.EPC);
    const naoExistem = codigos.filter(c => !retornados.includes(c));
    if (naoExistem.length > 0) {
      msgAlerta(`Codigos: ${JSON.stringify(naoExistem)} não existem ou estão desativados, faça a bipagem manual.`);
    }
  }

  habilitaBotaoEstorno(estorno) {
    if (this.buttonEstorna && estorno) {
      const estaComoEstorno = $(`${this.buttonEstorna}>i.fa-minus`).length > 0;
      !estaComoEstorno && $(this.buttonEstorna).trigger('click');
    } else {
      const estaComoEstorno = $(`${this.buttonEstorna}>i.fa-minus`).length > 0;
      estaComoEstorno && $(this.buttonEstorna).trigger('click');
    }
  }

  async bipa(itens, estorno = false) {
    const maxTentativas = 1;

    for (const [index, item] of itens.entries()) {
      const barra = !!item.BARRA_LOG ? item.BARRA_LOG : item.BARRA;

      if (barra === '') {
        msgAlerta(`Não existe barra para o RFID: ${item.EPC}`);
        continue;
      }

      this.habilitaBotaoEstorno(estorno)
      $(this.quantidade).val(1);
      $(this.codigoEPC).val(item.EPC);
      $(this.idItem).val(item.ID_ITEM);
      $(this.barra).val(estorno ? '-' + barra : barra);
      this.epc = item.EPC

      let tentativa = 0;
      let sucesso = false;

      while (tentativa < maxTentativas && !sucesso) {
        tentativa++;
        try {
          console.log(`[BIPA] [${index + 1}/${itens.length}] Tentativa ${tentativa} - EPC: ${item.EPC}`);
          if (this.callBackSaidaBarra) {
            await this.callBackSaidaBarra(); // tentativa com await
          } else {
            $(this.barra).trigger('blur');
          }
          if (item.BARRALOG_LIDA != 'S') {
            this.adicionaBarraLida()
          }

          sucesso = true;
        } catch (error) {
          console.warn(`[BIPA] Erro na tentativa ${tentativa} para EPC: ${item.EPC}`, error);
        }
      }

      if (!sucesso) {
        msgErro(`[BIPA] Falha após ${maxTentativas} tentativas para EPC: ${item.EPC}`);
      }
    }
  }

  async limpaBarras(barras) {
    await this.retornaCodigos(true, barras);
    this.listaBarrasBipadasEPC = this.listaBarrasBipadasEPC.filter(b => !barras.includes(b));
    this.listaBarrasForamBipadasEPC = [];
  }

  adicionaBarraLida() {
    if (this.epc) {
      this.listaBarrasBipadasEPC.push(this.epc);
      this.EPC = ''
      return true;
    }
    return false;
  }

  estornaBarra() {
    const epc = $(this.codigoEPC).val();
    this.listaBarrasBipadasEPC = this.listaBarrasBipadasEPC.filter(item => item !== epc);
    $(this.codigoEPC).val('');
  }

  getCodigosGravacao(numeroPedido, usaITAG = true) {
    return {
      Numero: numeroPedido,
      Id: '',
      CodigosEPC: usaITAG ? this.listaBarrasBipadasEPC.map(EPC => ({ EPC })) : []
    };
  }
}
