$('#tutorial').on('click', function () {
  $(document).ready(async function () {
    const driver = new Driver({
      doneBtnText: 'Sair',
      closeBtnText: 'Fechar',
      nextBtnText: 'Próximo',
      prevBtnText: 'Anterior',
      allowClose: false
    })
    driver.defineSteps([
      {
        element: "#tutorial-step1",
        popover: {
          title: "Campos",
          description:
            "Aqui se encontram os campos essenciais para consultar e gravar as informações.",
          position: "bottom",
        },
      },
      {
        element: '#divTabelaConsumos',
        popover: {
          title: 'Consumos',
          description: 'Aqui se encontram os consumos da ordem de produção informada.',
          position: 'top'
        }
      },
      {
        element: '#txtBarra',
        popover: {
          title: 'Barra',
          description: 'Aqui é possível fazer a baixa bipando uma barra de material.',
          position: 'top'
        }
      },
      {
        element: '#tabLotes',
        popover: {
          title: 'Estoque/Reserva',
          description: 'Aqui se encontram os lotes em estoque/reserva disponíveis.',
          position: 'top'
        }
      },
      {
        element: '#tabBaixas',
        popover: {
          title: 'Baixas',
          description: 'Aqui se encontram as baixas realizadas para a ordem de produção informada.',
          position: 'top'
        }
      }
    ])
    driver.start()
  })
})

$(document).ready(async function () {
  let indiceLinhaSelecionadaTabelaItens = 0
  const url = window.location.href
  const id = url.split('/')[url.split('/').length - 1]
  $('#mostrarEsconderMenu').trigger('click')

  let graficoPercentualCustoTimeout

  criarTabelaConferencia([])
  criarTabelaMediaConsumos([])

  function definirAlturaModalMediaConsumos() {
    const zoom = retornarValorMonetarioEmFloat($('body').css('zoom'))

    let alturaModal
    switch (zoom) {
      case 0.8:
        alturaModal = '124vh'
        break
      case 0.9:
        alturaModal = '110vh'
        break
      case 1:
        alturaModal = '99vh'
        break
      case 1.1:
        alturaModal = '90vh'
        break
      default:
        alturaModal = '95vh'
        break
    }

    $('#conteudoModalMediaConsumos').css({
      'min-height': alturaModal,
      'max-height': alturaModal,
    })
  }

  $(document).off('keydown')
  $(document).on('keydown', function (event) {
    if ((event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
      event.preventDefault()

      const direction = event.key === 'ArrowDown' ? 1 : -1
      const newIndex = indiceLinhaSelecionadaTabelaItens + direction

      if (newIndex >= 0 && newIndex < table.rows().count()) {
        selectRow(newIndex)
        const rowNode = table.row(newIndex).node()
        $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }
    }
    if (event.which === 121) {
      event.preventDefault()
      $('#btnMarkupProduto').trigger('click')
    }
  })

  function adicionarEventosCamposForm() {
    const $inputs = $('.stepControl:visible');

    $inputs.each(function (index) {
      $(this).on('keydown', function (e) {
        if (e.key === 'Enter') {
          e.preventDefault();
          const currentInput = $inputs.eq(index)
          if ((currentInput.attr('id') === 'txtMarkup') && (currentInput.val() === '')) {
            $('#btnMarkup').trigger('click')
            return
          }

          const $next = $inputs.eq(index + 1);
          if ($next.length) {
            $next.prop('disabled', false);
            habilitarBotoesRelacionados($next.attr('id'));
            setTimeout(() => {
              $next.focus();
            }, 0)
          }
        }
      });

      $(this).on('blur', function () {
        const $next = $inputs.eq(index + 1);
        if ($next.length && $next.prop('disabled')) {
          $next.prop('disabled', false);
          habilitarBotoesRelacionados($next.attr('id'));
        }
      });
    });

    function habilitarBotoesRelacionados(inputId) {
      const campo = inputId.replace('txt', '');
      $(`#btn${campo}`).prop('disabled', false).removeClass('disabledControl');
      $(`#btnLimpa${campo}`).prop('disabled', false).removeClass('disabledControl');
    }
  }

  $('#txtQuebra').on('keydown', function (e) {
    if (e.key === 'Enter') {
      $(this).trigger('blur')
    }
  })

  function adicionarEventosCamposIndicesModalMarkup() {
    const $inputs = $('.campoNacionalTabelaIndicesModalMarkup, .campoExportacaoTabelaIndicesModalMarkup');

    $inputs.each(function (index) {
      $(this).on('keydown', function (e) {
        if (e.key === 'Enter') {
          e.preventDefault();
          $(this).trigger('blur')
        }
      });
    });

    $('.campoNacionalTabelaIndicesModalMarkup').off('blur')
    $('.campoExportacaoTabelaIndicesModalMarkup').off('blur')
    $('.campoNacionalTabelaIndicesModalMarkup, .campoExportacaoTabelaIndicesModalMarkup').on('blur', () => recalcularValoresModalMarkup())
  }

  $('#btnCodigo').pesquisa_serverside(
    ['#txtCodigo', '#txtDescricao', '#txtUnidade'],
    ['CODIGO', 'DESCRICAO', 'UNIDADE'],
    ['DESCRICAO', 'DESCRICAO', 'UNIDADE'],
    '{"tabela":"PRODUTO", "camposSelect":[ "CODIGO", "DESCRICAO", "UNIDADE" ], "where": null}',
    'Pesquisa Produto',
    undefined,
    [true, true, true],
  )

  $('#btnLimpaCodigo').on('click', function () {
    $('#txtCodigo').val('')
    $('#txtDescricao').val('')
    $('#txtUnidade').val('')
    $('#txtTamanho').val('')
    $('#txtCodigo').trigger('blur')
  })

  $('#txtCodigo').on('input', function () {
    buscarDadosCodigoInformado(
      $(this).val()
    ).then(({ DESCRICAO: descricao, UNIDADE: unidade }) => {
      $('#txtDescricao').val(descricao)
      $('#txtUnidade').val(unidade)
    }).catch((error) => {
      msgErro('Ocorreu um erro ao buscar os dados.')
      console.error(error)
    })
  })

  $('#btnLimpaCor').on('click', function () {
    $('#txtCor').val('')
  })

  $('#txtTamanho').autocompletaSemDescricao(1, `JSON={ "tabela":"TABTAM", "camposSelect":["TAM"] }`,
    '#txtTamanho',
    'TAM',
    () => { },
  )

  $('#btnTamanho').pesquisaServersideSemDescricao(['#txtTamanho'], ['TAM'], '{"tabela":"TABTAM", "camposSelect":[ "TAM" ]}', 'Pesquisa Tamanho', undefined, [true])
  $('#btnLimpaTamanho').on('click', function () {
    $('#txtTamanho').val('')
  })

  $('#txtCodigo').on('blur', function () {
    const codigo = this.value
    atualizarPesquisaTamanho(codigo)
    atualizarPesquisaCor(codigo)
  })

  function atualizarPesquisaTamanho(codigo) {
    const pesquisa = codigo ? {
      tabela: "PRODUTO",
      camposSelect: ["FAIXA_ITEN.TAMANHO TAM"],
      innerJoin: [
        {
          tabela: "FAIXA",
          condicao: "PRODUTO.FAIXA = FAIXA.CODIGO",
        },
        {
          tabela: "FAIXA_ITEN",
          condicao: "FAIXA.CODIGO = FAIXA_ITEN.FAIXA",
        }
      ],
      where: [`PRODUTO.CODIGO = '${codigo}'`],
      camposSelectSubSelect: ["TAM"],
      groupBy: ["FAIXA_ITEN.TAMANHO"],
      groupBySubSelect: ["TAM"],
      camposWhereServerSide: ["FAIXA_ITEN.TAMANHO"],
    } : {
      tabela: "TABTAM",
      camposSelect: ["TAM"],
    }

    $('#txtTamanho').autocompletaSemDescricao(
      1,
      `JSON=${JSON.stringify(pesquisa)}`,
      '#txtTamanho',
      'TAM',
      () => { },
    )

    $('#btnTamanho').pesquisaServersideSemDescricao(['#txtTamanho'], ['TAM'], JSON.stringify(pesquisa), 'Pesquisa Tamanho', undefined, [true])
  }

  function atualizarPesquisaCor(codigo) {
    const pesquisa = codigo ? {
      tabela: "PA_ITEN",
      camposSelect: ["PA_ITEN.COR CHAVE", "CADCOR.DESCRICAO"],
      innerJoin: [
        {
          tabela: "CADCOR",
          condicao: "PA_ITEN.COR = CADCOR.COR",
        },
      ],
      where: [`PA_ITEN.CODIGO = '${codigo}'`],
      camposSelectSubSelect: ["CHAVE", "DESCRICAO"],
      groupBy: ["PA_ITEN.COR", "CADCOR.DESCRICAO"],
      groupBySubSelect: ["CHAVE", "DESCRICAO"],
      camposWhereServerSide: ["PA_ITEN.COR", "CADCOR.DESCRICAO"],
    } : {
      tabela: "CADCOR",
      camposSelect: ["COR", "DESCRICAO"]
    }

    $('#btnCor').pesquisa_serverside(
      ['#txtCor'],
      ['CHAVE', 'DESCRICAO'],
      ['DESCRICAO', 'DESCRICAO'],
      JSON.stringify(pesquisa),
      'Pesquisa Cor',
      undefined,
    )

    $('#txtCor').autocompleta(1, `JSON=${JSON.stringify(pesquisa)}`)
  }

  componenteFiltro('markup', false, false)

  function aplicarEstilosCamposDecimais() {
    $('.seisCasasDecimaisQuantityFormat').off('focus input focusout')
    $('.seisCasasDecimaisQuantityFormat').on('focus', function () {
      $(this).select()
    });

    $('.seisCasasDecimaisQuantityFormat').on('input', function () {
      let val = $(this).val();

      val = val.replace(/\./g, ',');

      val = val.replace(/[^0-9,]/g, '');

      let partes = val.split(',');
      if (partes.length > 1) {
        val = partes[0] + ',' + partes[1].substring(0, 6);
      }

      $(this).val(val);
    });

    $('.seisCasasDecimaisQuantityFormat').on('focusout', function () {
      let val = $(this).val();

      if (val) {
        if (val.startsWith(',')) {
          val = '0' + val;
        }
        let partes = val.split(',');
        let inteiro = partes[0];
        inteiro = safeParseInt(inteiro)
        if (!inteiro) {
          inteiro = '0'
        }
        let decimais = partes[1] || '';
        decimais = decimais.padEnd(6, '0');
        $(this).val(String(inteiro) + ',' + decimais);
      }
    });

    $('.quatroCasasDecimaisQuantityFormat').off('focus input focusout')
    $('.quatroCasasDecimaisQuantityFormat').on('focus', function () {
      $(this).select()
    });

    $('.quatroCasasDecimaisQuantityFormat').on('input', function () {
      let val = $(this).val();

      val = val.replace(/\./g, ',');

      val = val.replace(/[^0-9,]/g, '');

      let partes = val.split(',');
      if (partes.length > 1) {
        val = partes[0] + ',' + partes[1].substring(0, 4);
      }

      $(this).val(val);
    });

    $('.quatroCasasDecimaisQuantityFormat').on('focusout', function () {
      let val = $(this).val();

      if (val) {
        if (val.startsWith(',')) {
          val = '0' + val;
        }
        let partes = val.split(',');
        let inteiro = partes[0];
        inteiro = safeParseInt(inteiro)
        if (!inteiro) {
          inteiro = '0'
        }
        let decimais = partes[1] || '';
        decimais = decimais.padEnd(4, '0');
        $(this).val(String(inteiro) + ',' + decimais);
      }
    });

    $('.duasCasasDecimaisQuantityFormat').off('focus input focusout')
    $('.duasCasasDecimaisQuantityFormat').on('focus', function () {
      $(this).select()
    });

    $('.duasCasasDecimaisQuantityFormat').on('input', function () {
      let val = $(this).val();

      val = val.replace(/\./g, ',');

      val = val.replace(/[^0-9,]/g, '');

      let partes = val.split(',');
      if (partes.length > 1) {
        val = partes[0] + ',' + partes[1].substring(0, 2);
      }

      $(this).val(val);
    });

    $('.duasCasasDecimaisQuantityFormat').on('focusout', function () {
      let val = $(this).val();

      if (val) {
        if (val.startsWith(',')) {
          val = '0' + val;
        }
        let partes = val.split(',');
        let inteiro = partes[0];
        inteiro = safeParseInt(inteiro)
        if (!inteiro) {
          inteiro = '0'
        }
        let decimais = partes[1] || '';
        decimais = decimais.padEnd(2, '0');
        $(this).val(String(inteiro) + ',' + decimais);
      }
    });
  }

  aplicarEstilosCamposDecimais()

  const parametrosCustos = {
    considerarConsumosSemCores: false,
    calcularMediaPor: 'mediaTamanhoCor',
    buscarMaoDeObraDe: 'tempos',
    permitirAlterarCustoItens: false,
  }
  let tituloModalMediaConsumos = 'Média Tamanho/Cor'

  carregarParametrosCustos().then(() => {
    switch (parametrosCustos.calcularMediaPor) {
      case 'tamanho':
        tituloModalMediaConsumos = 'Tamanho'
        break
      case 'cor':
        tituloModalMedia = 'Cor'
        break
      case 'tamanhoCor':
        tituloModalMediaConsumos = 'Tamanho/Cor'
        break
      case 'mediaTamanhoCor':
        tituloModalMediaConsumos = 'Média Tamanho/Cor'
        break
      default:
        break
    }
    if (id === 'create') {
      adicionarEventosCamposForm()
    } else {
      atualizarEstadoCamposEdicao()
    }
  })

  function atualizarEstadoCamposEdicao() {
    $('#txtCodigo').prop('disabled', true)
    $('#btnCodigo').prop('disabled', true)
    $('#btnLimpaCodigo').prop('disabled', true)
    $('#txtDescricao').prop('disabled', false)
    $('#txtUnidade').prop('disabled', false)
    $('#txtMarkup').prop('disabled', false)
    $('#btnMarkup').prop('disabled', false)
    $('#btnLimpaMarkup').prop('disabled', false)
  }

  async function carregarParametrosCustos() {
    const parametros = await BuscaParametrosCustos()
    if (parametros[0]?.VALOR === '1') {
      parametrosCustos.considerarConsumosSemCores = true
    }
    $('#txtParametro0Custos').val(parametros[0]?.VALOR ?? '0') // temp

    switch (parametros[1]?.VALOR) {
      case '0': {
        parametrosCustos.calcularMediaPor = 'tamanho'
        $('#divTamanho').removeClass('d-none')
        break
      }
      case '1': {
        parametrosCustos.calcularMediaPor = 'cor'
        $('#divCor').removeClass('d-none')
        break
      }
      case '2': {
        parametrosCustos.calcularMediaPor = 'tamanhoCor'
        $('#divCor').removeClass('d-none')
        $('#divTamanho').removeClass('d-none')
        break
      }
      case '3':
        parametrosCustos.calcularMediaPor = 'mediaTamanhoCor'
        break
      default:
        break
    }

    switch (parametros[2]?.VALOR) {
      case '0':
        parametrosCustos.buscarMaoDeObraDe = 'tempos'
        break
      case '1':
        parametrosCustos.buscarMaoDeObraDe = 'setores'
        break
      case '2':
        parametrosCustos.buscarMaoDeObraDe = 'temposPrecoTempos'
        break
      case '3':
        parametrosCustos.buscarMaoDeObraDe = 'precoTerceiros'
        break
      default:
        break
    }
    $('#txtParametro1Custos').val(parametros[1]?.VALOR ?? '0') // temp

    $('#txtParametro2Custos').val(parametros[2]?.VALOR ?? '0') // temp

    if (parametros[3]?.VALOR === '1') {
      parametrosCustos.permitirAlterarCustoItens = true
    }

    if (['2', '3'].includes(parametros[4]?.VALOR)) {
      $('#divGraficoPercentuaisCusto').addClass('d-none')
      $('#divTabelaItens').removeClass('col-8')
      $('#divTabelaItens').addClass('col-12')
    }

    if (['1', '3'].includes(parametros[4]?.VALOR)) {
      $('#btnFotoProduto').addClass('d-none')
    } else {
      $('#btnFotoProduto').removeClass('d-none')
    }
  }

  $('#txtParametro0Custos').on('change', function () {
    if (this.value === '1') { // temp
      parametrosCustos.considerarConsumosSemCores = true
    } else {
      parametrosCustos.considerarConsumosSemCores = false
    }
  })

  $('#txtParametro1Custos').on('change', function () {
    switch (this.value) {
      case '0': {
        parametrosCustos.calcularMediaPor = 'tamanho'
        $('#divTamanho').removeClass('d-none')
        $('#divCor').addClass('d-none')
        break
      }
      case '1': {
        parametrosCustos.calcularMediaPor = 'cor'
        $('#divTamanho').addClass('d-none')
        $('#divCor').removeClass('d-none')
        break
      }
      case '2': {
        parametrosCustos.calcularMediaPor = 'tamanhoCor'
        $('#divTamanho').removeClass('d-none')
        $('#divCor').removeClass('d-none')
        break
      }
      case '3': {
        parametrosCustos.calcularMediaPor = 'mediaTamanhoCor'
        $('#divTamanho').addClass('d-none')
        $('#divCor').addClass('d-none')
        break
      }
      default:
        break
    }
  }) // temp

  $('#txtParametro2Custos').on('change', function () {
    switch (this.value) {
      case '0':
        parametrosCustos.buscarMaoDeObraDe = 'tempos'
        break
      case '1':
        parametrosCustos.buscarMaoDeObraDe = 'setores'
        break
      case '2':
        parametrosCustos.buscarMaoDeObraDe = 'temposPrecoTempos'
        break
      case '3':
        parametrosCustos.buscarMaoDeObraDe = 'precoTerceiros'
        break
      default:
        break
    } // temp
  })

  if (id && id !== 'create') {
    carregarCadastro(id)
  } else {
    carregarCotacoes()
    criarTabelaItens([])
    recarregarDadosItens()
  }

  async function carregarCadastro(chave) {
    $.LoadingOverlay('show')
    buscarDadosCadastro(
      chave
    ).then(({ capa, dadosMarkup, itens, custoTotal, itensComposicao, }) => {
      if (capa) {
        preencherDadosCapa(capa)
      }
      if (itens) {
        criarTabelaItens(itens)
      }
      if (dadosMarkup) {
        preencherDadosMarkup(dadosMarkup, custoTotal)
      }
      criarTabelaComposicaoGravar(itensComposicao)
    }).catch((error) => {
      console.error(error)
      msgErro('Ocorreu um erro ao carregar os dados.')
    }).finally(() => {
      $.LoadingOverlay('hide')
    })
  }

  function carregarCotacoes(data) {
    buscarCotacoes(data || new Date()).then(({ precoDolar, precoEuro }) => {
      $('#txtCotacaoDolar').val(retornarFloatFormatadoEmMonetario({ valor: precoDolar }))
      $('#txtCotacaoDolar').val(retornarFloatFormatadoEmMonetario({ valor: precoEuro }))
    }).catch((error) => {
      console.error(error)
      msgErro('Ocorreu um erro ao carregar as cotações.')
    })
  }

  async function buscarCotacoes(date) {
    const filtros = {
      data: date || formataData(new Date()),
    }

    const response = await requisicao("GET", `/Sisplan/formacaocustos/v1/cotacoes?`, `&FILTROS=${encodeURIComponent(JSON.stringify(filtros))}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado || {
        precoDolar: 0,
        precoEuro: 0,
      }
    }
  }

  async function buscarDadosCadastro(chave) {
    const response = await requisicao("GET", `/Sisplan/formacaocustos/v1/preco?`, `&ID=${chave}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado
    }
  }

  function retornarFiltros() {
    return {
      produto: $('#txtCodigo').val(),
      tamanho: $('#txtTamanho').val() || '',
      cor: pegaChave('#txtCor') || '',
      markup: pegaChave('#txtMarkup') || '',
      considerarConsumosSemCores: parametrosCustos.considerarConsumosSemCores,
      calcularMediaPor: parametrosCustos.calcularMediaPor,
      buscarMaoDeObraDe: parametrosCustos.buscarMaoDeObraDe,
    }
  }

  async function retornarItensProduto(filtros) {
    const response = await requisicao("GET", `/Sisplan/formacaocustos/v1/itensproduto?`, `&FILTROS=${encodeURIComponent(JSON.stringify(filtros))}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado
    }
  }

  function preencherDadosCapa(data) {
    const {
      codigo,
      descricao,
      unidade,
      tamanho,
      cor,
      descricaoCor,
      markup,
      descricaoMarkup,
      dataCadastro,
      pesoBruto,
      quebra,
      precoDolar,
      precoEuro,
      idPreco,
      dataAtualizacao,
      indiceMarkup,
      status,
      pesoLiquido,
      padrao,
    } = data

    insereValor('#txtCodigo', codigo)
    insereValor('#txtDescricao', descricao)
    insereValor('#txtUnidade', unidade)
    insereValor('#txtTamanho', tamanho)
    insereValor('#txtCor', cor, descricaoCor)
    insereValor('#txtMarkup', markup, descricaoMarkup)
    insereValor('#txtCadastro', dataCadastro.substring(0, 10))
    insereValor('#txtPesoBruto', retornarFloatFormatadoEmMonetario({ valor: pesoBruto, quantidadeCasasDecimais: 6 }))
    insereValor('#txtQuebra', retornarFloatFormatadoEmMonetario({ valor: quebra, quantidadeCasasDecimais: 6 }))
    insereValor('#txtPrecoDolar', retornarFloatFormatadoEmMonetario({ valor: precoDolar }))
    insereValor('#txtPrecoEuro', retornarFloatFormatadoEmMonetario({ valor: precoEuro }))
    insereValor('#txtIdPreco', idPreco)
    insereValor('#txtAtualizacao', retornarDataISOEmYMD({ dataISO: dataAtualizacao, separadorData: '-', usarUTC: true }))
    insereValor('#txtIndiceMarkup', retornarFloatFormatadoEmMonetario({ valor: indiceMarkup, quantidadeCasasDecimais: 6 }))
    // insereValor('#txtStatus', status) // TODO corrigir
    insereValor('#txtPesoLiquido', retornarFloatFormatadoEmMonetario({ valor: pesoLiquido, quantidadeCasasDecimais: 6 }))
    $('#cbPadrao').prop('checked', padrao)
  }

  function criarTabelaItens(data) {
    if ($.fn.DataTable.isDataTable('#tabelaItens')) {
      $('#tabelaItens').DataTable().destroy()
      $('#tabelaItens').empty()
    }

    const columns = [
      {
        data: 'ordem',
        title: 'Ordem',
        render: function (data) {
          return '<div style="text-align:start;"> ' +
            '    <button class="btn btn-info btn-sm dropdown-toggle btnVerificaOpcoes" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> ' +
            '      ' + data + ' ' +
            '    </button> ' +
            '    <div class="dropdown-menu"> ' +
            '    <button class="dropdown-item" type="button" id="btnBuscarComposicao">Buscar composição</button>     ' +
            '</div>'
        }
      },
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'custo',
        title: 'Custo',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'valor',
        title: 'Valor',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'grupo',
        title: 'Grupo',
      },
      {
        data: 'descricaoGrupo',
        title: 'Descrição Grupo',
      },
    ]

    const table = $("#tabelaItens").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
      scrollY: '350px',
      select: {
        style: 'single',
        toggleable: false,
      },
    }).draw(false)

    function selectRow(index) {
      const row = table.row(index)
      if (row.node()) {
        table.rows().deselect()
        row.select()
        indiceLinhaSelecionadaTabelaItens = index
      }
    }

    $('#tabelaItens_wrapper .dataTables_scrollBody').off('wheel')
    $('#tabelaItens_wrapper .dataTables_scrollBody').on('wheel', function (event) {
      event.preventDefault()

      const direction = event.originalEvent.deltaY > 0 ? 1 : -1
      const newIndex = indiceLinhaSelecionadaTabelaItens + direction


      if (newIndex >= 0 && newIndex < table.rows().count()) {
        selectRow(newIndex)


        const rowNode = table.row(newIndex).node()
        $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }
    })

    table.off('select')
    table.on('select', function (_e, _dt, type, indexes) {
      if (type === 'row') {
        indiceLinhaSelecionadaTabelaItens = indexes[0]
        const descricaoColIndex = table.column((idx) => table.settings()[0].aoColumns[idx].data === 'valor').index();
        const row = table.row(indiceLinhaSelecionadaTabelaItens)

        const $celula = $(row.node()).find('td').eq(descricaoColIndex);
        $($celula).css('color', 'red');
      }
    })

    $(document).off('keydown')
    $(document).on('keydown', function (event) {
      if ((event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
        event.preventDefault()

        const direction = event.key === 'ArrowDown' ? 1 : -1
        const newIndex = indiceLinhaSelecionadaTabelaItens + direction

        if (newIndex >= 0 && newIndex < table.rows().count()) {
          selectRow(newIndex)
          const rowNode = table.row(newIndex).node()
          $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      }
      if (event.which === 121) {
        event.preventDefault()
        $('#btnMarkupProduto').trigger('click')
      }
    })

    selectRow(indiceLinhaSelecionadaTabelaItens)
    setTimeout(() => {
      table.columns.adjust().draw(false)
    }, 1000)
  }

  function recarregarDadosItens() {
    const itens = $("#tabelaItens").DataTable().data().toArray()
    const quebra = retornarValorMonetarioEmFloat($('#txtQuebra').val())
    const totais = retornarTotais(itens, quebra)
    calcularTotaisItens(totais)
    carregarDadosMarkup(totais?.custoTotalComQuebra, pegaChave('#txtMarkup'))
    carregarGraficoPercentualCusto()
  }

  function criarTabelaMediaConsumos(data, height) {
    if ($.fn.DataTable.isDataTable('#tabelaMediaConsumos')) {
      $('#tabelaMediaConsumos').DataTable().destroy()
      $('#tabelaMediaConsumos').empty()
    }

    const columns = [
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'custo',
        title: 'Custo',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'valor',
        title: 'Valor',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'grupo',
        title: 'Grupo',
      },
      {
        data: 'descricaoGrupo',
        title: 'Descrição Grupo',
      },
      {
        data: 'aplicacao',
        title: 'Aplicação',
      },
      {
        data: 'descricaoAplicacao',
        title: 'Descrição Aplicação',
      },
      {
        data: 'setor',
        title: 'Setor',
      },
      {
        data: 'descricaoSetor',
        title: 'Descrição Setor',
      },
    ]

    $("#tabelaMediaConsumos").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollY: height ?? "245px",
    }).draw(false)
  }

  function criarTabelaConferencia(data, height) {
    if ($.fn.DataTable.isDataTable('#tabelaConferencia')) {
      $('#tabelaConferencia').DataTable().destroy()
      $('#tabelaConferencia').empty()
    }

    const columns = [
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'corProduto',
        title: 'Cor Produto',
      },
      {
        data: 'descricaoCorProduto',
        title: 'Desc. Cor Produto',
      },
      {
        data: 'corMaterial',
        title: 'Cor Material',
      },
      {
        data: 'descricaoCorMaterial',
        title: 'Desc. Cor Material',
      },
      {
        data: 'tamanho',
        title: 'Tamanho',
      },
      {
        data: 'consumo',
        title: 'Consumo',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'grupo',
        title: 'Grupo',
      },
      {
        data: 'descricaoGrupo',
        title: 'Descrição Grupo',
      },
      {
        data: 'aplicacao',
        title: 'Aplicação',
      },
      {
        data: 'descricaoAplicacao',
        title: 'Descrição Aplicação',
      },
      {
        data: 'setor',
        title: 'Setor',
      },
      {
        data: 'descricaoSetor',
        title: 'Descrição Setor',
      },
    ]

    const table = $("#tabelaConferencia").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
      scrollY: height ?? "295px",
      searching: true,
      filter: true,
    }).draw(false)

    const titleContainer = $('#tabelaConferencia_wrapper > div:first-child > div:first-child')
    titleContainer.addClass("flex align-items-end")
    titleContainer.html('<h5 class="pl-1">Consumos</h5>')

    const totalConsumo = retornarTotalConsumoItens(table.data().toArray())

    $('#txtTotalConsumoModalMediaConsumos').val(retornarFloatFormatadoEmMonetario({ valor: totalConsumo, quantidadeCasasDecimais: 6 }))

    table.on('search.dt', function () {
      const totalConsumo = retornarTotalConsumoItens(table.rows({ filter: 'applied' }).data().toArray())

      $('#txtTotalConsumoModalMediaConsumos').val(retornarFloatFormatadoEmMonetario({ valor: totalConsumo, quantidadeCasasDecimais: 6 }))
    })
  }

  function retornarTotalConsumoItens(itens) {
    try {
      const total = itens.reduce((acc, item) => acc + item.consumo, 0)

      return total ?? 0
    } catch (error) {
      console.error(error)
      return 0
    }
  }

  $('#modalMediaConsumos').on('shown.bs.modal', function () {
    carregarModalMediaConsumos()
    definirAlturaModalMediaConsumos()
  })

  $('#modalMediaConsumos').on('hidden.bs.modal', function () {
    if ($.fn.DataTable.isDataTable('#tabelaConferencia')) {
      $('#tabelaConferencia').DataTable().destroy()
      $('#tabelaConferencia').empty()
    }
    if ($.fn.DataTable.isDataTable('#tabelaMediaConsumos')) {
      $('#tabelaMediaConsumos').DataTable().destroy()
      $('#tabelaMediaConsumos').empty()
    }
    if ($.fn.DataTable.isDataTable('#tabelaConferenciaMaoDeObra')) {
      $('#tabelaConferenciaMaoDeObra').DataTable().destroy()
      $('#tabelaConferenciaMaoDeObra').empty()
    }
  })

  function retornarAlturasTabelas(alturaBody) {
    const alturaPagina = window.innerHeight

    if (alturaPagina < 700) {
      return {
        mediaConsumos: alturaBody * 0.325,
        conferencia: alturaBody * 0.25,
      }
    }

    if (alturaPagina < 800) {
      return {
        mediaConsumos: alturaBody * 0.375,
        conferencia: alturaBody * 0.275,
      }
    }

    if (alturaPagina < 900) {
      return {
        mediaConsumos: alturaBody * 0.40,
        conferencia: alturaBody * 0.275,
      }
    }

    return {
      mediaConsumos: alturaBody * 0.425,
      conferencia: alturaBody * 0.30,
    }
  }

  $('#btnBuscarItens').on('click', async function () {
    await carregarDadosProduto()
  })

  async function carregarDadosProduto() {
    try {
      $.LoadingOverlay('show')
      const filtros = retornarFiltros()
      if (validarFiltrosProduto(filtros)) {
        const { itens } = await retornarItensProduto(filtros)
        criarTabelaItens(itens || [])
        recarregarDadosItens()
      }
    } catch (error) {
      msgErro(error || 'Ocorreu um erro ao buscar os dados.')
      console.error(error)
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  function validarFiltrosProduto(filtros) {
    const calcularMediaPor = filtros.calcularMediaPor
    if (!calcularMediaPor) {
      msgErro('Parâmetro 1 dos custos não configurado, impossível continuar.')
      return
    }
    const { produto, tamanho, cor, markup } = filtros
    if (!produto) {
      msgErro('Produto não informado, impossível continuar.')
      return
    }
    if (!tamanho && ["tamanho", "tamanhoCor"].includes(calcularMediaPor)) {
      msgErro('Tamanho não informado, impossível continuar.')
      return
    }
    if (!cor && ["cor", "tamanhoCor"].includes(calcularMediaPor)) {
      msgErro('Cor não informada, impossível continuar.')
      return
    }

    if (!markup) {
      msgErro('Markup não informado, impossível continuar.')
      return
    }
    return true
  }

  async function buscarDadosCodigoInformado(produto) {
    const pesquisa = {
      camposSelect: ['DESCRICAO', 'UNIDADE'],
      tabela: 'PRODUTO',
      where: [`CODIGO = '${produto}'`],
    }
    const result = await retornaJsonPesquisaPadrao(JSON.stringify(pesquisa))
    return result[0] || {
      DESCRICAO: '',
      UNIDADE: '',
    }
  }

  $('#txtCadastro').on('blur', function () {
    const data = new Date($('#txtCadastro').val())
    if (data instanceof Date && !isNaN(data)) {
      carregarCotacoes(data)
    }
  })

  $('#txtMarkup').on('blur', function () {
    if (!this.value) {
      return
    }

    $('#modalMediaConsumos').modal('show')
  })

  function carregarDadosMarkup(custoTotal, markup) {
    buscarDadosMarkup(
      {
        idPreco: id,
        markup,
        custoTotal,
      }
    ).then((data) => {
      preencherDadosMarkup(data, custoTotal)
    })
  }

  function preencherDadosMarkup(data, custoTotal) {
    alimentarPrazosEPrecosMarkup(data)
    $('#txtIndiceMarkup').val(retornarFloatFormatadoEmMonetario({ valor: data?.indiceMarkup, quantidadeCasasDecimais: 4 }))

    destacarPrazoPadrao({ prazos: data?.prazos, prazoPadrao: data?.prazoPadrao })

    if (!data?.indices || data?.indices?.length === 0) {
      return
    }
    criarTabelaIndicesModalMarkup(data?.indices)
    const totais = retornarTotaisModalMarkup(data?.indices)
    $('#txtTotalNacionalModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: totais?.indiceNacional, quantidadeCasasDecimais: 4 }))
    $('#txtTotalExportacaoModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: totais?.indiceExportacao, quantidadeCasasDecimais: 4 }))
    alimentarCamposCustoModalMarkup({ taxa: data?.taxa, dias: data?.prazos, prazoPadrao: data?.prazoPadrao, totais, custoTotal })
    alimentarPrazosEPrecosModalMarkup({ ...data.prazos, ...data.precosPeca, custoTotal })
  }

  function destacarPrazoPadrao({ prazos, prazoPadrao }) {
    $('.rowMarkup1').css('color', 'var(--font-color)')
    $('.rowMarkup2').css('color', 'var(--font-color)')
    $('.rowMarkup3').css('color', 'var(--font-color)')
    $('.rowMarkup4').css('color', 'var(--font-color)')
    $('.rowMarkup5').css('color', 'var(--font-color)')
    $('.rowMarkup6').css('color', 'var(--font-color)')
    $('.rowMarkup7').css('color', 'var(--font-color)')

    if (prazos?.prazo1 === prazoPadrao) {
      $('.rowMarkup1').css('color', 'red')
      return
    }
    if (prazos?.prazo2 === prazoPadrao) {
      $('.rowMarkup2').css('color', 'red')
      return
    }
    if (prazos?.prazo3 === prazoPadrao) {
      $('.rowMarkup3').css('color', 'red')
      return
    }
    if (prazos?.prazo4 === prazoPadrao) {
      $('.rowMarkup4').css('color', 'red')
      return
    }
    if (prazos?.prazo5 === prazoPadrao) {
      $('.rowMarkup5').css('color', 'red')
      return
    }
    if (prazos?.prazo6 === prazoPadrao) {
      $('.rowMarkup6').css('color', 'red')
      return
    }
    if (prazos?.prazo7 === prazoPadrao) {
      $('.rowMarkup7').css('color', 'red')
      return
    }
  }

  function alimentarPrazosEPrecosMarkup({ prazos, precosPeca }) {
    if (!precosPeca?.precoAVista || precosPeca?.precoAVista <= 0) {
      return
    }

    $('#txtValorPc0').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.precoAVista }))
    $('#txtValorKg0').val('0,00')
    $('.rowMarkup0').removeClass('d-none')

    if (!prazos?.prazo1 || prazos?.prazo1 <= 0) {
      return
    }

    $('#txtPrazo1').val(prazos?.prazo1)
    $('#txtValorPc1').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco1 }))
    $('#txtValorKg1').val('0,00')
    $('.rowMarkup1').removeClass('d-none')

    if (!prazos?.prazo2 || prazos?.prazo2 <= 0) {
      return
    }
    $('#txtPrazo2').val(prazos?.prazo2)
    $('#txtValorPc2').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco2 }))
    $('#txtValorKg2').val('0,00')
    $('.rowMarkup2').removeClass('d-none')

    if (!prazos?.prazo3 || prazos?.prazo3 <= 0) {
      return
    }
    $('#txtPrazo3').val(prazos?.prazo3)
    $('#txtValorPc3').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco3 }))
    $('#txtValorKg3').val('0,00')
    $('.rowMarkup3').removeClass('d-none')

    if (!prazos?.prazo4 || prazos?.prazo4 <= 0) {
      return
    }
    $('#txtPrazo4').val(prazos?.prazo4)
    $('#txtValorPc4').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco4 }))
    $('#txtValorKg4').val('0,00')
    $('.rowMarkup4').removeClass('d-none')

    if (!prazos?.prazo5 || prazos?.prazo5 <= 0) {
      return
    }
    $('#txtPrazo5').val(prazos?.prazo5)
    $('#txtValorPc5').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco5 }))
    $('#txtValorKg5').val('0,00')
    $('.rowMarkup5').removeClass('d-none')

    if (!prazos?.prazo6 || prazos?.prazo6 <= 0) {
      return
    }
    $('#txtPrazo6').val(prazos?.prazo6)
    $('#txtValorPc6').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco6 }))
    $('#txtValorKg6').val('0,00')
    $('.rowMarkup6').removeClass('d-none')

    if (!prazos?.prazo7 || prazos?.prazo7 <= 0) {
      return
    }
    $('#txtPrazo7').val(prazos?.prazo7)
    $('#txtValorPc7').val(retornarFloatFormatadoEmMonetario({ valor: precosPeca?.preco7 }))
    $('#txtValorKg7').val('0,00')
    $('.rowMarkup7').removeClass('d-none')
  }

  async function buscarDadosMarkup({ idPreco, markup, custoTotal }) {
    const filtros = {
      idPreco,
      markup,
      custoTotal,
    }
    const response = await requisicao("GET", `/Sisplan/formacaocustos/v1/dadosmarkup?`, `&FILTROS=${encodeURIComponent(JSON.stringify(filtros))}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado || {
        prazo1: 0,
        prazo2: 0,
        prazo3: 0,
        prazo4: 0,
        prazo5: 0,
        prazo6: 0,
        prazo7: 0,
      }
    }
  }

  function retornarPrefixoTitulosModais() {
    return `[${$('#txtCodigo').val()} - ${$('#txtDescricao').val()}]`
  }

  $('#btnMarkupProduto').on('click', function () {
    const markup = pegaChave('#txtMarkup')
    if (validarDadosAbrirModalMarkup(markup)) {
      const prefixoTitulo = retornarPrefixoTitulosModais()
      const titulo = `${prefixoTitulo} - Markup Produto`
      $('#tituloModalMarkup').html(titulo)

      $('#modalMarkup').modal('show')
    }
  })

  function validarDadosAbrirModalMarkup(markup) {
    if (!markup) {
      msgErro('Markup não informado, impossível continuar.')
      return
    }

    return true
  }

  function criarTabelaIndicesModalMarkup(data) {
    if ($.fn.DataTable.isDataTable('#tabelaIndicesModalMarkup')) {
      $('#tabelaIndicesModalMarkup').DataTable().destroy()
      $('#tabelaIndicesModalMarkup').empty()
    }

    const columns = [
      {
        title: 'Código',
        data: 'codigo',
      },
      {
        title: 'Descrição',
        data: 'descricao',
      },
      {
        title: 'Nacional',
        data: 'indiceNacional',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 4 })
          return `<div class="input-group-append">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right quatroCasasDecimaisQuantityFormat campoNacionalTabelaIndicesModalMarkup" id="txtNacional${row}" name="txtNacional${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        title: 'Exportação',
        data: 'indiceExportacao',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 4 })
          return `<div class="input-group-append">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right quatroCasasDecimaisQuantityFormat campoExportacaoTabelaIndicesModalMarkup" id="txtExportacao${row}" name="txtExportacao${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        title: 'Valor',
        data: 'valor',
        class: "text-right",
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        title: 'Tipo',
        data: 'tipo',
      },
      {
        title: 'Percentual Correção',
        data: 'percentualCorrecao',
        visible: false,
      },
      {
        title: 'Valor Correção',
        data: 'valorCorrecao',
        visible: false,
      },
      {
        title: 'Percentual Industrial',
        data: 'percentualIndustrial',
        visible: false,
      },
      {
        title: 'Valor Industrial',
        data: 'valorIndustrial',
        visible: false,
      },
    ]

    $("#tabelaIndicesModalMarkup").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      info: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
    }).draw(false)

    adicionarEventosCamposIndicesModalMarkup()
  }

  function alimentarCamposCustoModalMarkup({ taxa, dias, prazoPadrao, totais, custoTotal }) {
    const { prazo1, prazo2, prazo3, prazo4, prazo5, prazo6, prazo7, } = dias
    const precoAVista = retornarValorMonetarioEmFloat($('#txtValorPc0').val())
    const indice = retornarValorMonetarioEmFloat($('#txtIndiceMarkup').val())

    $('#txtTaxaModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: taxa, quantidadeCasasDecimais: 4 }))
    $('#txtMarkupModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: totais?.indiceNacional, quantidadeCasasDecimais: 4 })}%`)
    $('#txtIndiceModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: indice, quantidadeCasasDecimais: 4 })}%`)
    $('#txtMarkupSemLucroModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: totais?.indiceNacionalSemLucro, quantidadeCasasDecimais: 4 })}%`)
    $('#txtCustoModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: custoTotal, quantidadeCasasDecimais: 4 }))
    $('#txtPrecoAvistaModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: precoAVista, quantidadeCasasDecimais: 4 }))
    $('#txtTotalNacionalModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: totais?.indiceNacional, quantidadeCasasDecimais: 4 }))
    $('#txtTotalExportacaoModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: totais?.indiceExportacao, quantidadeCasasDecimais: 4 }))

    if (prazo1 && prazo1 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo1}">${prazo1}</option>`)
    }
    if (prazo2 && prazo2 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo2}">${prazo2}</option>`)
    }
    if (prazo3 && prazo3 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo3}">${prazo3}</option>`)
    }
    if (prazo4 && prazo4 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo4}">${prazo4}</option>`)
    }
    if (prazo5 && prazo5 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo5}">${prazo5}</option>`)
    }
    if (prazo6 && prazo6 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo6}">${prazo6}</option>`)
    }
    if (prazo7 && prazo7 > 0) {
      $('#selectDiasModalMarkup').append(`<option value="${prazo7}">${prazo7}</option>`)
    }
    if (prazoPadrao > 0) {
      $('#selectDiasModalMarkup').val(prazoPadrao)
    }
  }

  function alimentarPrazosEPrecosModalMarkup({
    custoTotal,
    prazo1,
    prazo2,
    prazo3,
    prazo4,
    prazo5,
    prazo6,
    prazo7,
    preco1,
    preco2,
    preco3,
    preco4,
    preco5,
    preco6,
    preco7,
  }) {
    if (!prazo1 || prazo1 <= 0) {
      return
    }

    let indiceParcela = 0

    if (!prazo1 || prazo1 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup1').val(prazo1)
    $('#txtPrecoModalMarkup1').val(retornarFloatFormatadoEmMonetario({ valor: preco1 }))
    indiceParcela = custoTotal / preco1
    $('#txtIndiceParcelaModalMarkup1').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup1').removeClass('d-none')


    if (!prazo2 || prazo2 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup2').val(prazo2)
    $('#txtPrecoModalMarkup2').val(retornarFloatFormatadoEmMonetario({ valor: preco2 }))
    indiceParcela = custoTotal / preco2
    $('#txtIndiceParcelaModalMarkup2').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup2').removeClass('d-none')


    if (!prazo3 || prazo3 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup3').val(prazo3)
    $('#txtPrecoModalMarkup3').val(retornarFloatFormatadoEmMonetario({ valor: preco3 }))
    indiceParcela = custoTotal / preco3
    $('#txtIndiceParcelaModalMarkup3').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup3').removeClass('d-none')


    if (!prazo4 || prazo4 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup4').val(prazo4)
    $('#txtPrecoModalMarkup4').val(retornarFloatFormatadoEmMonetario({ valor: preco4 }))
    indiceParcela = custoTotal / preco4
    $('#txtIndiceParcelaModalMarkup4').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup4').removeClass('d-none')


    if (!prazo5 || prazo5 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup5').val(prazo5)
    $('#txtPrecoModalMarkup5').val(retornarFloatFormatadoEmMonetario({ valor: preco5 }))
    indiceParcela = custoTotal / preco5
    $('#txtIndiceParcelaModalMarkup5').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup5').removeClass('d-none')


    if (!prazo6 || prazo6 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup6').val(prazo6)
    $('#txtPrecoModalMarkup6').val(retornarFloatFormatadoEmMonetario({ valor: preco6 }))
    indiceParcela = custoTotal / preco6
    $('#txtIndiceParcelaModalMarkup6').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup6').removeClass('d-none')


    if (!prazo7 || prazo7 <= 0) {
      return
    }
    $('#txtPrazoModalMarkup7').val(prazo7)
    $('#txtPrecoModalMarkup7').val(retornarFloatFormatadoEmMonetario({ valor: preco7 }))
    indiceParcela = custoTotal / preco7
    $('#txtIndiceParcelaModalMarkup7').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
    $('.modalRowMarkup7').removeClass('d-none')
  }

  function retornarTotaisModalMarkup(indices) {
    try {
      const totais = indices.reduce((acc, indice) => {
        return {
          indiceNacional: acc.indiceNacional + indice.indiceNacional,
          indiceExportacao: acc.indiceExportacao + indice.indiceExportacao,
          indiceNacionalSemLucro: acc.indiceNacionalSemLucro + (indice.tipo === '1 - MRG_LUCRO' ? 0 : indice.indiceNacional),
        }
      }, {
        indiceNacional: 0,
        indiceExportacao: 0,
        indiceNacionalSemLucro: 0,
      })

      return totais
    } catch {
      return {
        indiceNacional: 0,
        indiceExportacao: 0,
        indiceNacionalSemLucro: 0,
      }
    }
  }

  function recalcularValoresModalMarkup() {
    try {
      const itens = $('#tabelaIndicesModalMarkup')
        .DataTable()
        .data()
        .toArray()
        .map((item, index) => {
          const indiceNacional = retornarValorMonetarioEmFloat($(`#txtNacional${index}`).val())
          const indiceExportacao = retornarValorMonetarioEmFloat($(`#txtExportacao${index}`).val())

          return {
            tipo: item.tipo,
            indiceNacional,
            indiceExportacao,
          }
        })

      const totais = retornarTotaisModalMarkup(itens)
      const arrayPrazos = $('#selectDiasModalMarkup option')
        .map(function () {
          return this.value
        })
        .get()

      const prazos = {}
      arrayPrazos.forEach((item, index) => {
        prazos[`prazo${index + 1}`] = item
      })

      const custoTotal = retornarValorMonetarioEmFloat($('#txtCustoModalMarkup').val())
      const taxa = retornarValorMonetarioEmFloat($('#txtTaxaModalMarkup').val())
      const precoVenda = retornarValorMonetarioEmFloat($('#txtPrecoAvistaModalMarkup').val())

      const filtros = {
        prazos,
        custoTotal,
        taxa,
        margemContribuicaoTotal: totais.indiceNacional,
        precoVenda,
        custoIndustrialFixo: 0,
        margemLucro: totais.indiceNacional - totais.indiceNacionalSemLucro,
        codigoMarkup: pegaChave('#txtMarkup'),
      }

      retornarValoresRecalculados(filtros).then((data) => {
        alimentarValoresRecalculados({ ...data, exportacao: totais.indiceExportacao })
      })
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao recalcular valores.')
    }
  }

  async function retornarValoresRecalculados(filtros) {
    const response = await requisicao("POST", `/Sisplan/formacaocustos/v1/recalcularprecos?`, '', JSON.stringify(filtros), 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado || {
        precoDolar: 0,
        precoEuro: 0,
      }
    }
  }

  function alimentarValoresRecalculados({ markup, markupSemLucro, taxa, precos, exportacao, indiceMarkup }) {
    $('#txtTaxaModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: taxa, quantidadeCasasDecimais: 4 }))
    $('#txtMarkupModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: markup, quantidadeCasasDecimais: 4 })}%`)
    $('#txtMarkupSemLucroModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: markupSemLucro, quantidadeCasasDecimais: 4 })}%`)
    $('#txtTotalNacionalModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: markup, quantidadeCasasDecimais: 4 }))
    $('#txtTotalExportacaoModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: exportacao, quantidadeCasasDecimais: 4 }))
    $('#txtPrecoAvistaModalMarkup').val(retornarFloatFormatadoEmMonetario({ valor: precos?.precoAVista, quantidadeCasasDecimais: 4 }))
    $('#txtIndiceModalMarkup').val(`${retornarFloatFormatadoEmMonetario({ valor: indiceMarkup, quantidadeCasasDecimais: 4 })}%`)

    let indiceParcela = 0
    const custoTotal = retornarValorMonetarioEmFloat($('#txtCustoModalMarkup').val())

    $('#txtPrecoModalMarkup1').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco1 }))
    indiceParcela = custoTotal / precos?.preco1 ?? 1
    $('#txtIndiceParcelaModalMarkup1').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup2').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco2 }))
    indiceParcela = custoTotal / precos?.preco2 ?? 1
    $('#txtIndiceParcelaModalMarkup2').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup3').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco3 }))
    indiceParcela = custoTotal / precos?.preco3 ?? 1
    $('#txtIndiceParcelaModalMarkup3').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup4').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco4 }))
    indiceParcela = custoTotal / precos?.preco4 ?? 1
    $('#txtIndiceParcelaModalMarkup4').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup5').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco5 }))
    indiceParcela = custoTotal / precos?.preco5 ?? 1
    $('#txtIndiceParcelaModalMarkup5').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup6').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco6 }))
    indiceParcela = custoTotal / precos?.preco6 ?? 1
    $('#txtIndiceParcelaModalMarkup6').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))

    $('#txtPrecoModalMarkup7').val(retornarFloatFormatadoEmMonetario({ valor: precos?.preco7 }))
    indiceParcela = custoTotal / precos?.preco7 ?? 1
    $('#txtIndiceParcelaModalMarkup7').val(retornarFloatFormatadoEmMonetario({ valor: indiceParcela, quantidadeCasasDecimais: 4 }))
  }

  async function carregarModalMediaConsumos() {
    try {
      $.LoadingOverlay('show')
      const filtros = retornarFiltros()
      if (validarFiltrosProduto(filtros)) {
        const prefixoTitulo = retornarPrefixoTitulosModais()
        const titulo = `${prefixoTitulo} - ${tituloModalMediaConsumos}`
        $('#tituloModalMediaConsumos').html(titulo)

        const dados = await retornarItensProduto(filtros)
        const alturaBody = parseInt($('#modalMarkupBody').css('height').replace('px', ''))
        const alturasTabelas = retornarAlturasTabelas(alturaBody)
        criarTabelaConferencia(dados.itensConferencia ?? [], alturasTabelas.conferencia)
        criarTabelaMediaConsumos(dados.itens ?? [], alturasTabelas.mediaConsumos)
        criarTabelaConferenciaMaoDeObra(dados.itensMaoDeObra ?? [], alturasTabelas.conferencia)
        $('#modalMediaConsumos').modal('show')
      }
    } catch (error) {
      msgErro(error || 'Ocorreu um erro ao buscar os dados.')
      console.error(error)
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  $('#btnConfirmarMediaConsumos').on('click', function () {
    confirmarMediaConsumos()
  })

  function confirmarMediaConsumos() {
    try {
      $.LoadingOverlay('show')
      const itensMedia = $('#tabelaMediaConsumos').DataTable().data().toArray()
      const itens = retornarItensFinaisCustos(itensMedia)
      criarTabelaItens(itens)
      recarregarDadosItens()
    } catch (error) {
      msgErro('Ocorreu um erro ao confirmar os dados.')
      console.error(error)
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  function retornarItensFinaisCustos(itensMedia) {
    const resultado = []
    let ordem = 1
    itensMedia.forEach((item) => {
      const index = resultado.findIndex((el) => el.codigo === item.codigo)
      if (index !== -1) {
        resultado[index].quantidade += item.quantidade
        resultado[index].valor += item.valor
        return
      }

      resultado.push({ ...item, ordem })
      ordem++
    })

    return resultado
  }

  function retornarTotais(itens, quebra) {
    try {
      const custoTotal = itens?.reduce((acc, item) => acc + item.valor, 0) ?? 0

      const custoTotalComQuebra = custoTotal / ((100 - quebra) / 100)

      return {
        custoTotal: isNaN(custoTotal) ? 0 : custoTotal,
        custoTotalComQuebra: isNaN(custoTotalComQuebra) ? 0 : custoTotalComQuebra,
      }

    } catch (error) {
      console.error(error)
      return {
        custoTotal: 0,
        custoTotalComQuebra: 0,
      }
    }
  }

  $('#txtQuebra').on('blur', function () {
    const itens = $('#tabelaItens').DataTable().data().toArray()
    const quebra = retornarValorMonetarioEmFloat($('#txtQuebra').val())
    const totais = retornarTotais(itens, quebra)
    calcularTotaisItens(totais)
    carregarDadosMarkup(totais?.custoTotalComQuebra, pegaChave('#txtMarkup'))
  })

  function calcularTotaisItens(totais) {
    $('#txtCustoTotal').val(retornarFloatFormatadoEmMonetario({ valor: totais.custoTotal, quantidadeCasasDecimais: 6 }))
    $('#txtCustoTotalComQuebra').val(retornarFloatFormatadoEmMonetario({ valor: totais.custoTotalComQuebra, quantidadeCasasDecimais: 6 }))
  }

  $('#txtPesoBruto, #txtPesoLiquido').on('blur', function () {
    const pesoBruto = retornarValorMonetarioEmFloat($('#txtPesoBruto').val())
    const pesoLiquido = retornarValorMonetarioEmFloat($('#txtPesoLiquido').val())

    const perda = retornarPerda(pesoBruto, pesoLiquido)

    $('#txtPerda').val(retornarFloatFormatadoEmMonetario({ valor: perda, quantidadeCasasDecimais: 6 }))
  })

  function retornarPerda(pesoBruto, pesoLiquido) {
    if (pesoBruto <= 0 || pesoLiquido <= 0) {
      return
    }

    const resultado = (pesoBruto - pesoLiquido) / (pesoBruto * 100)

    if (isNaN(resultado) || resultado <= 0) {
      return 0
    }

    return resultado
  }

  $('#btnConfirmarModalMarkup').on('click', function () {
    atualizarDadosMarkup()
  })

  function atualizarDadosMarkup() {
    try {
      $.LoadingOverlay('show')
      const indice = retornarValorMonetarioEmFloat($('#txtIndiceModalMarkup').val())
      const precoAVista = retornarValorMonetarioEmFloat($('#txtPrecoAvistaModalMarkup').val())
      const preco1 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup1').val())
      const preco2 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup2').val())
      const preco3 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup3').val())
      const preco4 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup4').val())
      const preco5 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup5').val())
      const preco6 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup6').val())
      const preco7 = retornarValorMonetarioEmFloat($('#txtPrecoModalMarkup7').val())

      const precosPeca = {
        precoAVista,
        preco1,
        preco2,
        preco3,
        preco4,
        preco5,
        preco6,
        preco7,
      }

      const prazo1 = $('#txtPrazoModalMarkup1').val()
      const prazo2 = $('#txtPrazoModalMarkup2').val()
      const prazo3 = $('#txtPrazoModalMarkup3').val()
      const prazo4 = $('#txtPrazoModalMarkup4').val()
      const prazo5 = $('#txtPrazoModalMarkup5').val()
      const prazo6 = $('#txtPrazoModalMarkup6').val()
      const prazo7 = $('#txtPrazoModalMarkup7').val()

      const prazos = {
        prazo1,
        prazo2,
        prazo3,
        prazo4,
        prazo5,
        prazo6,
        prazo7,
      }

      alimentarPrazosEPrecosMarkup({ prazos, precosPeca })
      $('#txtIndiceMarkup').val(retornarFloatFormatadoEmMonetario({ valor: indice, quantidadeCasasDecimais: 4 }))

      $('#modalMarkup').modal('hide')
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao confirmar os dados.')
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  function retornarCapaGravar() {
    const codigo = $('#txtCodigo').val()
    const descricao = $('#txtDescricao').val()
    const unidade = $('#txtUnidade').val()
    const tamanho = $('#txtTamanho').val()
    const cor = pegaChave('#txtCor')
    const markup = pegaChave('#txtMarkup')
    const dataCadastro = $('#txtCadastro').val()
    const pesoBruto = retornarValorMonetarioEmFloat($('#txtPesoBruto').val())
    const quebra = retornarValorMonetarioEmFloat($('#txtQuebra').val())
    const precoDolar = retornarValorMonetarioEmFloat($('#txtPrecoDolar').val())
    const precoEuro = retornarValorMonetarioEmFloat($('#txtPrecoEuro').val())
    const idPreco = $('#txtIdPreco').val()
    const dataAtualizacao = $('#txtAtualizacao').val() || retornarDataISOEmYMD({ separadorData: '-', usarUTC: true })
    const indiceMarkup = retornarValorMonetarioEmFloat($('#txtIndiceMarkup').val())
    const pesoLiquido = retornarValorMonetarioEmFloat($('#txtPesoLiquido').val())
    const precoVenda = retornarValorMonetarioEmFloat($('#txtValorPc0').val())
    const custoTotal = retornarValorMonetarioEmFloat($('#txtCustoTotalComQuebra').val())
    const padrao = $('#cbPadrao').prop('checked')
    const preco1 = retornarValorMonetarioEmFloat($('#txtValorPc1').val())
    const preco2 = retornarValorMonetarioEmFloat($('#txtValorPc2').val())
    const preco3 = retornarValorMonetarioEmFloat($('#txtValorPc3').val())
    const preco4 = retornarValorMonetarioEmFloat($('#txtValorPc4').val())
    const preco5 = retornarValorMonetarioEmFloat($('#txtValorPc5').val())
    const preco6 = retornarValorMonetarioEmFloat($('#txtValorPc6').val())
    const preco7 = retornarValorMonetarioEmFloat($('#txtValorPc7').val())
    const prazoPadrao = $('#selectDiasModalMarkup').val()
    const taxa = retornarValorMonetarioEmFloat($('#txtTaxaModalMarkup').val())

    const capa = {
      codigo,
      descricao,
      unidade,
      tamanho,
      cor,
      markup,
      dataCadastro,
      pesoBruto,
      quebra,
      precoDolar,
      precoEuro,
      idPreco,
      dataAtualizacao,
      indiceMarkup,
      pesoLiquido,
      precoVenda,
      custoTotal,
      padrao,
      preco1,
      preco2,
      preco3,
      preco4,
      preco5,
      preco6,
      preco7,
      prazoPadrao,
      taxa,
    }

    return capa
  }

  function retornarDadosGravar() {
    const capa = retornarCapaGravar()
    const itens = $('#tabelaItens').DataTable().data().toArray()
    const indicesMarkup = retornarIndicesMarkup()
    const itensComposicao = $('#tabelaComposicaoGravar').DataTable().data().toArray()

    return {
      capa,
      itens,
      indicesMarkup,
      itensComposicao,
    }
  }

  function retornarIndicesMarkup() {
    const data = $('#tabelaIndicesModalMarkup').DataTable().data().toArray()

    const indices = data.map((item, index) => ({
      codigo: item.codigo,
      descricao: item.descricao,
      diasReducao: item.indiceReducao,
      indiceExportacao: retornarValorMonetarioEmFloat($(`#txtEsportacao${index}`).val()),
      indiceNacional: retornarValorMonetarioEmFloat($(`#txtNacional${index}`).val()),
      percentualCorrecao: item.percentualCorrecao,
      percentualIndustrial: item.percentualIndustrial,
      tipo: item.tipo,
      tipoIndice: item.tipoIndice,
      valor: item.valor,
      valorCorrecao: item.valorCorrecao,
      valorIndustrial: item.valorIndustrial,
    }))

    return indices
  }

  function validarDadosGravar(dados) {
    if (!dados) {
      msgErro('Dados inválidos, impossível continuar.')
      return false
    }

    if (!dados.capa?.markup) {
      msgErro('Markup não informado, impossível continuar.')
      return false
    }

    if (!dados.itens || dados.itens.length === 0) {
      msgErro('Nenhum item adicionado, impossível continuar.')
      return false
    }

    if (dados.itens.some((item) => item.codigo === dados.capa?.codigo)) {
      msgErro('Produto não pode conter ele mesmo nos itens, impossível continuar.')
      return false
    }

    if (dados.capa?.indiceMarkup > 1) {
      msgErro('Índice do markup não pode ser superior a 1, impossível continuar.')
      return false
    }

    return true
  }

  $('#btnGravar').on('click', function () {
    const dadosGravar = retornarDadosGravar()
    if (!validarDadosGravar(dadosGravar)) {
      return
    }
    gravar(dadosGravar)
  })

  async function gravar(dados) {
    try {
      $.LoadingOverlay('show')
      const response = await requisicao("POST", `/sisplan/formacaocustos/v1/preco?`, '', JSON.stringify(dados), 3600000)
      const json = await response.json()

      if (!json) {
        return
      }
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }


      toastr.success("Dados gravados com sucesso!", "Confirmação", {
        toastClass: "alert",
        iconClasses: {
          error: "alert-error",
          info: "alert-info",
          success: "alert-success",
          warning: "alert-warning",
        },
        positionClass: "toast-top-center",
        progressBar: true,
        timeOut: 1000,
        fadeOut: 1000,
        onHidden() {
          $('#txtIdPreco').val(resultado?.id ?? 0)
        }
      }).css({
        "margin-top": "20%",
        width: "500px",
        "max-width": "500px",
      })
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao gravar os dados.')
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  $('#btnAlterar').on('click', function () {
    const itens = $('#tabelaItens').DataTable().data().toArray()
    const itensComposicao = $('#tabelaComposicaoGravar').DataTable().data().toArray()
    carregarModalAlteracao(itens, itensComposicao)
  })

  function carregarModalAlteracao(itens, itensComposicao) {
    const prefixoTitulo = retornarPrefixoTitulosModais()
    const titulo = `${prefixoTitulo} - Alteração de Itens`
    $('#tituloModalAlteracao').html(titulo)
    criarTabelaItensAlteracao(itens)
    criarTabelaComposicaoAlteracao(itensComposicao)
    $('#modalAlteracao').modal('show')
  }

  function criarTabelaItensAlteracao(data) {
    if ($.fn.DataTable.isDataTable('#tabelaItensAlteracao')) {
      $('#tabelaItensAlteracao').DataTable().destroy()
      $('#tabelaItensAlteracao').empty()
    }

    const columns = [
      {
        data: 'ordem',
        title: 'Ordem',
      },
      {
        data: 'codigo',
        title: 'Código',
        render: function (value, _1, _2, { row }) {
          return `<div>
                    <div class="input-group">
                      <input type="text" class="input-default focus form-control stepControlAlteracao${row}" id="txtCodigoAlteracao${row}" value="${value}" name="txtCodigoAlteracao${row}" placeholder="Código">
                      <div class="input-group-append">
                        <button class="btn bg-danger" id="btnCodigoAlteracao${row}" name="btnCodigoAlteracao${row}" data-button="absolute" type="button"><i class="m-0 p-0 fas fa-search"></i></button>
                      </div>
                    </div>
                  </div>`
        }
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 6 })
          return `<div class="input-group-append justify-content-end">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right seisCasasDecimaisQuantityFormat stepControlAlteracao${row}" id="txtQuantidadeAlteracao${row}" name="txtQuantidadeAlteracao${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        data: 'custo',
        title: 'Custo',
        className: 'text-right',
        render: function (data, _1, _2, { row }) {
          const valorFormatado = retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
          return `<div class="input-group-append justify-content-end">
                <input type="text" value="${valorFormatado}" ${!parametrosCustos.permitirAlterarCustoItens && 'disabled'} style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right seisCasasDecimaisQuantityFormat stepControlAlteracao${row}" id="txtCustoAlteracao${row}" name="txtCustoAlteracao${row}" placeholder="0,000000">
            </div>`
        },
      },
      {
        data: 'valor',
        title: 'Valor',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'grupo',
        title: 'Grupo',
      },
      {
        data: 'descricaoGrupo',
        title: 'Descrição Grupo',
      },
    ]

    const table = $("#tabelaItensAlteracao").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollY: '65vh',
      select: {
        style: 'single',
        toggleable: false,
      },
    }).draw(false)

    let selectedRowIndex = 0

    function selectRow(index) {
      const row = table.row(index)
      if (row.node()) {
        table.rows().deselect()
        row.select()
      }
    }

    $('#tabelaItensAlteracao_wrapper .dataTables_scrollBody').off('wheel')
    $('#tabelaItensAlteracao_wrapper .dataTables_scrollBody').on('wheel', function (event) {
      event.preventDefault()

      const direction = event.originalEvent.deltaY > 0 ? 1 : -1
      const newIndex = selectedRowIndex + direction

      if (newIndex >= 0 && newIndex < table.rows().count()) {
        selectRow(newIndex)

        const rowNode = table.row(newIndex).node()
        $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }
    })

    table.off('select')
    table.on('select', function (_e, _dt, type, indexes) {
      if (type === 'row') {
        selectedRowIndex = indexes[0]
      }
    })

    $(document).off('keydown')
    $(document).on('keydown', function (event) {
      if ((event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
        event.preventDefault()

        const direction = event.key === 'ArrowDown' ? 1 : -1
        const newIndex = selectedRowIndex + direction

        if (newIndex >= 0 && newIndex < table.rows().count()) {
          selectRow(newIndex)
          const rowNode = table.row(newIndex).node()
          $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      }
    })

    selectRow(selectedRowIndex)
  }

  function retornarPesquisaAlteracaoItem(codigo) {
    const pesquisa = {
      camposSelect: [
        'MAT_PRECO.CODIGO',
        'MAT_PRECO.DESCRICAO',
        'MAT_PRECO.UNIDADE',
        'MAT_PRECO.CODIGO_IMPRESSAO GRUPO',
        'PRECO_GRUPO.DESCRICAO DESC_GRUPO',
        'MAT_PRECO.PRECO_1 CUSTO',
      ],
      tabela: 'MAT_PRECO',
      leftJoin: [
        {
          tabela: 'PRECO_GRUPO',
          condicao: 'MAT_PRECO.CODIGO_IMPRESSAO = PRECO_GRUPO.CODIGO',
        }
      ],
      groupBy: [
        'MAT_PRECO.CODIGO',
        'MAT_PRECO.DESCRICAO',
        'MAT_PRECO.UNIDADE',
        'MAT_PRECO.CODIGO_IMPRESSAO',
        'PRECO_GRUPO.DESCRICAO',
        'MAT_PRECO.PRECO_1',
      ],
      camposSelectSubSelect: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'GRUPO',
        'DESC_GRUPO',
        'CUSTO',
      ],
      groupBySubSelect: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'GRUPO',
        'DESC_GRUPO',
        'CUSTO',
      ],
      camposWhereServerSide: [
        'MAT_PRECO.CODIGO',
        'MAT_PRECO.DESCRICAO',
      ]
    }

    if (codigo) {
      pesquisa.where = [`MAT_PRECO.CODIGO = '${codigo}'`]
    }

    return pesquisa
  }

  function adicionarEventosBotoesItensAlteracao(index, row) {
    let valorAnterior = $(`#txtCodigoAlteracao${index}`).val()
    $(`#btnCodigoAlteracao${index}`).off('pesquisa_serverside')
    $(`#btnCodigoAlteracao${index}`).pesquisa_serverside(
      [`#txtCodigoAlteracao${index}`],
      ['CODIGO', 'DESCRICAO', 'UNIDADE'],
      ['DESCRICAO', 'DESCRICAO', 'UNIDADE'],
      JSON.stringify(retornarPesquisaAlteracaoItem()),
      'Pesquisa Item',
      () => {
        setTimeout(() => {
          const valorSelecionado = $(`#txtCodigoAlteracao${index}`).val()
          atualizarItemAlteracaoComDadosDoCodigoInformado(valorSelecionado, index, row)
          if (valorAnterior !== valorSelecionado) {
            valorAnterior = valorSelecionado
            atualizarItensComposicaoAposAlterarItem(row.data())
          }
        }, 0)
      },
      [true],
    )
  }

  let debounceTimer;

  function adicionarEventosInputsItensAlteracao(index, row) {
    $(`#txtCodigoAlteracao${index}`).off('focus keydown input blur')
    let valorAnterior = $(`#txtCodigoAlteracao${index}`).val()

    let enterCampoCodigoFoiPressionado = false
    $(`#txtCodigoAlteracao${index}`)
      .on('focus', function () {
        const input = this
        input.selectionStart = input.selectionEnd = input.value.length
      })
      .on('keydown', function (e) {
        if (e.key === 'Enter') {
          e.preventDefault()
          enterCampoCodigoFoiPressionado = true
          $(`#txtQuantidadeAlteracao${index}`).focus()
          return
        }
      })
      .on('input', function () {
        if (debounceTimer) {
          clearTimeout(debounceTimer);
        }

        if (enterCampoCodigoFoiPressionado) {
          enterCampoCodigoFoiPressionado = false
          return
        }

        debounceTimer = setTimeout(async () => {
          try {
            const valorDigitado = this.value
            if (!valorDigitado) {
              return
            }
            $(this).prop('disabled', true)
            await atualizarItemAlteracaoComDadosDoCodigoInformado(valorDigitado, index, row)
            $(`#txtCodigoAlteracao${index}`).focus()
          } finally {
            $(this).prop('disabled', false)
          }
        }, 300);
      })
      .on('blur', function () {
        if (valorAnterior !== this.value) {
          valorAnterior = this.value
          atualizarItensComposicaoAposAlterarItem(row.data())
        }
      })

    let enterCampoQuantidadeFoiPressionado = false
    $(`#txtQuantidadeAlteracao${index}`).off('keydown blur')
    $(`#txtQuantidadeAlteracao${index}`)
      .on('keydown', function (e) {
        enterCampoQuantidadeFoiPressionado = (e.key === 'Enter')
        if (enterCampoQuantidadeFoiPressionado) {
          e.preventDefault()
          $(this).blur()
        }
      })
      .on('blur', function () {
        try {
          const quantidade = retornarValorMonetarioEmFloat(this.value)
          const data = row.data()
          const custo = retornarValorMonetarioEmFloat(data.custo)
          const valor = quantidade * custo

          if (valor === undefined || valor === null || isNaN(valor)) {
            row.data({ ...data, valor: 0 }).draw(false)
          } else {
            row.data({ ...data, quantidade, custo, valor }).draw(false)
          }

          if (enterCampoQuantidadeFoiPressionado) {
            $(`#txtCustoAlteracao${index}`).focus()
          }
        } catch { }
        finally {
          enterCampoQuantidadeFoiPressionado = false
        }
      })

    let enterCampoCustoFoiPressionado = false
    $(`#txtCustoAlteracao${index}`).off('keydown blur')
    $(`#txtCustoAlteracao${index}`)
      .on('keydown', function (e) {
        enterCampoCustoFoiPressionado = (e.key === 'Enter')
        if (enterCampoCustoFoiPressionado) {
          e.preventDefault()
          $(this).blur()
        }
      })
      .on('blur', function () {
        try {
          const custo = retornarValorMonetarioEmFloat(this.value)
          const data = row.data()
          const quantidade = retornarValorMonetarioEmFloat(data.quantidade)
          const valor = quantidade * custo

          if (valor === undefined || valor === null || isNaN(valor)) {
            row.data({ ...data, valor: 0 }).draw(false)
          } else {
            row.data({ ...data, quantidade, custo, valor }).draw(false)
          }

          if (enterCampoCustoFoiPressionado) {
            $(`#txtCodigoAlteracao${index + 1}`)?.focus()
          }
        } catch { }
        finally {
          enterCampoCustoFoiPressionado = false
        }
      })
  }

  $('#tabelaItensAlteracao').on('draw.dt', function () {
    adicionarEventosItensAlteracao($(this).DataTable())
  })

  async function atualizarItemAlteracaoComDadosDoCodigoInformado(codigo, index, row) {
    try {
      const {
        descricao,
        unidade,
        grupo,
        descricaoGrupo,
        custo,
      } = await buscarDadosCodigoAlteracaoInformado(codigo)

      const rowData = row.data()
      const valor = rowData.quantidade * custo
      const newData = {
        ...rowData,
        codigo,
        descricao,
        unidade,
        grupo,
        descricaoGrupo,
        custo,
        valor,
      }
      row.data(newData).draw(false)
    } catch (error) {
      msgErro('Ocorreu um erro ao buscar os dados.')
      console.error(error)
    }
  }

  function adicionarEventosItensAlteracao(table) {
    table.rows().every((index) => {
      const row = table.row(index)
      adicionarEventosBotoesItensAlteracao(index, row)
      adicionarEventosInputsItensAlteracao(index, row)
    })
  }

  async function buscarDadosCodigoAlteracaoInformado(codigo) {
    const pesquisa = retornarPesquisaAlteracaoItem(codigo)
    const result = await retornaJsonPesquisaPadrao(JSON.stringify(pesquisa))
    return {
      descricao: result[0]?.DESCRICAO ?? '',
      unidade: result[0]?.UNIDADE ?? '',
      custo: result[0]?.CUSTO ?? 0,
      grupo: result[0]?.GRUPO ?? '',
      descricaoGrupo: result[0]?.DESC_GRUPO ?? '',
    }
  }

  $('#btnIncluirAlteracao').on('click', function () {
    adicionarRegistroTabelaItensAlteracao()
  })

  function adicionarRegistroTabelaItensAlteracao(data) {
    const table = $('#tabelaItensAlteracao').DataTable()
    const dadosInserir = {
      ...{
        ordem: table.data().toArray().reduce((acc, item) => acc < item.ordem ? item.ordem : acc, 0) + 1,
        codigo: '',
        descricao: '',
        unidade: '',
        quantidade: 0,
        custo: 0,
        valor: 0,
        grupo: '',
        descricaoGrupo: '',
      },
      ...data,
    }

    table.row.add(dadosInserir).draw(false)
    const index = table.rows().count() - 1
    const row = table.row(index)
    if (row.node()) {
      table.rows().deselect()
      row.select()
      setTimeout(() => {
        $(row.node()).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }, 150)
    }
  }

  $('#btnExcluirAlteracao').on('click', function () {
    excluirItemAlteracao()
  })

  function excluirItemAlteracao() {
    let datatable = $('#tabelaItensAlteracao').DataTable()
    const indicesSelecionados = datatable.rows({ selected: true }).indexes().toArray()
    if (!indicesSelecionados || indicesSelecionados.length === 0) {
      msgErro('Nenhum registro selecionado, impossível continuar.')
      return
    }
    if (indicesSelecionados.length > 1) {
      msgErro('Ocorreu um erro ao excluir, por favor tente novamente.')
      data.row(0).select()
      return
    }
    const [indiceSelecionado] = indicesSelecionados
    const dadosLinhaRemovida = datatable.row(indiceSelecionado).data()
    datatable.row(indiceSelecionado).remove()
    atualizarItensComposicaoAposRemoverItem(dadosLinhaRemovida)
    recalcularDadosTabelaItensAlteracao()
    datatable = $('#tabelaItensAlteracao').DataTable()
    const ultimoIndiceDisponivel = datatable.rows().count() - 1
    const proximoIndiceASerSelecionado = indiceSelecionado > ultimoIndiceDisponivel ? ultimoIndiceDisponivel : indiceSelecionado
    if (proximoIndiceASerSelecionado >= 0) {
      const row = datatable.row(proximoIndiceASerSelecionado)
      row.select()
      setTimeout(() => {
        $(row.node()).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }, 150)
    }
  }

  function recalcularDadosTabelaItensAlteracao() {
    const table = $('#tabelaItensAlteracao').DataTable()
    const data = table.data().toArray()
    const novosDados = data.map((item, idx) => ({
      ...item,
      ordem: idx + 1,
    }))

    criarTabelaItensAlteracao(novosDados)
  }

  $('#btnConfirmarAlteracao').on('click', function () {
    confirmarAlteracao()
  })

  function confirmarAlteracao() {
    try {
      $.LoadingOverlay('show')
      const itens = $('#tabelaItensAlteracao').DataTable().data().toArray().filter((item) => item.codigo && item.valor && !isNaN(item.valor) && item.valor > 0)
      criarTabelaItens(itens)
      recarregarDadosItens()
      const itensComposicao = $('#tabelaComposicaoAlteracao').DataTable().data().toArray()
      criarTabelaComposicaoGravar(itensComposicao)
      $('#modalAlteracao').modal('hide')
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao confirmar os dados.')
    } finally {
      $.LoadingOverlay('hide')
    }
  }

  $('#tabelaItensAlteracao').on('draw.dt', function () {
    aplicarEstilosCamposDecimais()
    const dados = $('#tabelaItensAlteracao').DataTable().data().toArray()
    const totalCusto = dados.reduce((acc, item) => acc + item.valor, 0)
    $('#txtTotalCustoModalAlteracao').val(retornarFloatFormatadoEmMonetario({ valor: totalCusto, quantidadeCasasDecimais: 6 }))
  })

  $('#tabelaIndicesModalMarkup').on('draw.dt', function () {
    aplicarEstilosCamposDecimais()
  })

  $('#modalAlteracao').on('shown.bs.modal', function () {
    $('#tabelaItensAlteracao').DataTable().columns.adjust().draw(false)
  })

  $('#tabelaItens').on('click', '#btnBuscarComposicao', async function () {
    const data = $('#tabelaItens').DataTable().row($(this).parents('tr')).data();
    const idPreco = $('#txtIdPreco').val()
    carregarComposicaoMaterial(data, idPreco)
  })

  $('#modalComposicao').on('shown.bs.modal', function () {
    $('#tabelaComposicao').DataTable().columns.adjust().draw(false)
  })

  let indiceLinhaSelecionadaTabelaComposicao = 0

  function criarTabelaComposicao(data = []) {
    if ($.fn.DataTable.isDataTable('#tabelaComposicao')) {
      $('#tabelaComposicao').DataTable().destroy()
      $('#tabelaComposicao').empty()
    }

    const columns = [
      {
        data: 'ordem',
        title: 'Ordem',
      },
      {
        data: 'codigo',
        title: 'Código',
        render: function (value, _1, _2, { row }) {
          return `<div>
                    <div class="input-group flex-nowrap">
                      <input type="text" class="input-default focus form-control stepControlComposicao${row}" id="txtCodigoComposicao${row}" value="${value}" name="txtCodigoComposicao${row}" placeholder="Código" style="min-width: 20ch">
                      <div class="input-group-append">
                        <button class="btn bg-danger" id="btnCodigoComposicao${row}" name="btnCodigoComposicao${row}" data-button="absolute" type="button"><i class="m-0 p-0 fas fa-search"></i></button>
                      </div>
                    </div>
                  </div>`
        }
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 6 })
          return `<div class="input-group-append justify-content-end">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right seisCasasDecimaisQuantityFormat stepControlComposicao${row}" id="txtQuantidadeComposicao${row}" name="txtQuantidadeComposicao${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        data: 'custo',
        title: 'Custo',
        className: 'text-right',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 6 })
          return `<div class="input-group-append justify-content-end">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right seisCasasDecimaisQuantityFormat stepControlComposicao${row}" id="txtCustoComposicao${row}" name="txtCustoComposicao${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        data: 'quebra',
        title: 'Quebra',
        className: 'text-right',
        render: function (value, _1, _2, { row }) {
          const formattedValue = retornarFloatFormatadoEmMonetario({ valor: value, quantidadeCasasDecimais: 6 })
          return `<div class="input-group-append justify-content-end">
                      <input type="text" value="${formattedValue}" style="min-width: 15ch; max-width: 20ch" class="input-default focus form-control validate text-right seisCasasDecimaisQuantityFormat stepControlComposicao${row}" id="txtQuebraComposicao${row}" name="txtQuebraComposicao${row}" placeholder="0,000000">
                  </div>`
        },
      },
      {
        data: 'valor',
        title: 'Valor',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'acumulado',
        title: 'Acumulado',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'ultimaAtualizacao',
        title: 'Atualizado Em',
        render: function (data) {
          return retornarDataISOEmYMD({ dataISO: data, reverso: true, usarUTC: true })
        }
      },
    ]

    const table = $("#tabelaComposicao").DataTable({
      info: false,
      order: false,
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
      scrollY: '275px',
      select: {
        style: 'single',
        toggleable: false,
      },
    }).draw(false)

    function selectRow(index) {
      const row = table.row(index)
      if (row.node()) {
        table.rows().deselect()
        row.select()
      }
    }

    $('#tabelaComposicao_wrapper .dataTables_scrollBody').off('wheel')
    $('#tabelaComposicao_wrapper .dataTables_scrollBody').on('wheel', function (event) {
      event.preventDefault()

      const direction = event.originalEvent.deltaY > 0 ? 1 : -1
      const newIndex = indiceLinhaSelecionadaTabelaComposicao + direction

      if (newIndex >= 0 && newIndex < table.rows().count()) {
        selectRow(newIndex)

        const rowNode = table.row(newIndex).node()
        $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }
    })

    table.off('select')
    table.on('select', function (_e, _dt, type, indexes) {
      if (type === 'row') {
        indiceLinhaSelecionadaTabelaComposicao = indexes[0]
      }
    })

    $(document).off('keydown')
    $(document).on('keydown', function (event) {
      if ((event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
        event.preventDefault()

        const direction = event.key === 'ArrowDown' ? 1 : -1
        const newIndex = indiceLinhaSelecionadaTabelaComposicao + direction

        if (newIndex >= 0 && newIndex < table.rows().count()) {
          selectRow(newIndex)
          const rowNode = table.row(newIndex).node()
          $(rowNode).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      }
    })

    selectRow(indiceLinhaSelecionadaTabelaComposicao)
    adicionarEventosComposicao(table)
  }

  $('#modalComposicao').on('shown.bs.modal', function () {
    $('#tabelaComposicao').DataTable().columns.adjust().draw(false)
  })

  $('#btnExcluirItemComposicao').on('click', function () {
    excluirItemComposicao()
  })

  function excluirItemComposicao() {
    let datatable = $('#tabelaComposicao').DataTable()
    const indicesSelecionados = datatable.rows({ selected: true }).indexes().toArray()
    if (!indicesSelecionados || indicesSelecionados.length === 0) {
      msgErro('Nenhum registro selecionado, impossível continuar.')
      return
    }
    if (indicesSelecionados.length > 1) {
      msgErro('Ocorreu um erro ao excluir, por favor tente novamente.')
      data.row(0).select()
      return
    }
    const [indiceSelecionado] = indicesSelecionados
    datatable.row(indiceSelecionado).remove()
    recalcularDadosTabelaComposicao()
    datatable = $('#tabelaComposicao').DataTable()
    const ultimoIndiceDisponivel = datatable.rows().count() - 1
    const proximoIndiceASerSelecionado = indiceSelecionado > ultimoIndiceDisponivel ? ultimoIndiceDisponivel : indiceSelecionado
    if (proximoIndiceASerSelecionado >= 0) {
      const row = datatable.row(proximoIndiceASerSelecionado)
      row.select()
      setTimeout(() => {
        $(row.node()).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }, 150)
    }
  }

  $('#tabelaComposicao').on('draw.dt', function () {
    aplicarEstilosCamposDecimais()
  })

  function retornarPesquisaItemComposicao(codigo) {
    const pesquisa = {
      camposSelect: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'PRECO_1 CUSTO',
        'DT_ULT_ATUALIZACAO ATUALIZADO_EM',
      ],
      tabela: 'MAT_PRECO',
      groupBy: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'PRECO_1',
        'DT_ULT_ATUALIZACAO',
      ],
      camposSelectSubSelect: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'CUSTO',
        'ATUALIZADO_EM',
      ],
      groupBySubSelect: [
        'CODIGO',
        'DESCRICAO',
        'UNIDADE',
        'CUSTO',
        'ATUALIZADO_EM',
      ],
      camposWhereServerSide: [
        'CODIGO',
        'DESCRICAO',
      ]
    }

    if (codigo) {
      pesquisa.where = [`MAT_PRECO.CODIGO = '${codigo}'`]
    }

    return pesquisa
  }

  function adicionarEventosBotoesComposicao(index, row) {
    $(`#btnCodigoComposicao${index}`).pesquisa_serverside(
      [`#txtCodigoComposicao${index}`],
      ['CODIGO', 'DESCRICAO'],
      ['DESCRICAO', 'DESCRICAO'],
      JSON.stringify(retornarPesquisaItemComposicao()),
      'Pesquisa Item',
      () => {
        setTimeout(() => {
          const valorSelecionado = $(`#txtCodigoComposicao${index}`).val()
          atualizarItemComposicaoComDadosDoCodigoInformado(valorSelecionado, index, row)
        }, 0)
      },
      [true],
    )
  }

  let debounceTimerComposicao;

  function adicionarEventosInputsComposicao(index, row) {

    $(`#txtCodigoComposicao${index}`).on('focus', function () {
      const input = this
      input.selectionStart = input.selectionEnd = input.value.length
    })

    let enterCampoCodigoFoiPressionado = false
    $(`#txtCodigoComposicao${index}`)
      .on('keydown', function (e) {
        if (e.key === 'Enter') {
          e.preventDefault()
          enterCampoCodigoFoiPressionado = true
          $(`#txtQuantidadeComposicao${index}`).focus()
          return
        }
      })
      .on('input', function () {
        if (debounceTimerComposicao) {
          clearTimeout(debounceTimerComposicao);
        }

        if (enterCampoCodigoFoiPressionado) {
          enterCampoCodigoFoiPressionado = false
          return
        }

        debounceTimerComposicao = setTimeout(async () => {
          try {
            const valorDigitado = this.value
            if (!valorDigitado) {
              return
            }
            $(this).prop('disabled', true)
            await atualizarItemComposicaoComDadosDoCodigoInformado(valorDigitado, index, row)
            $(`#txtCodigoComposicao${index}`).focus()
          } finally {
            $(this).prop('disabled', false)
          }
        }, 300);
      })

    let enterCampoQuantidadeFoiPressionado = false
    $(`#txtQuantidadeComposicao${index}`)
      .on('keydown', function (e) {
        enterCampoQuantidadeFoiPressionado = (e.key === 'Enter')
        if (enterCampoQuantidadeFoiPressionado) {
          e.preventDefault()
          $(this).blur()
        }
      })
      .on('blur', function () {
        try {
          const quantidade = retornarValorMonetarioEmFloat(this.value)
          const data = row.data()
          const quebra = retornarValorMonetarioEmFloat(data.quebra)
          const custo = retornarValorMonetarioEmFloat(data.custo)
          const valor = retornarValorItemComposicao({ custo, quantidade, quebra })

          if (!valor || isNaN(valor)) {
            row.data({ ...data, custo: 0, quantidade: 0, quebra: 0, valor: 0 })
          } else {
            row.data({ ...data, custo, quantidade, quebra, valor })
          }
          recalcularDadosTabelaComposicao()

          if (enterCampoQuantidadeFoiPressionado) {
            $(`#txtCustoComposicao${index}`).focus()
          }
        } catch { }
        finally {
          enterCampoQuantidadeFoiPressionado = false
        }
      })

    let enterCampoCustoFoiPressionado = false
    $(`#txtCustoComposicao${index}`)
      .on('keydown', function (e) {
        enterCampoCustoFoiPressionado = (e.key === 'Enter')
        if (enterCampoCustoFoiPressionado) {
          e.preventDefault()
          $(this).blur()
        }
      })
      .on('blur', function () {
        try {
          const custo = retornarValorMonetarioEmFloat(this.value)
          const data = row.data()
          const quebra = retornarValorMonetarioEmFloat(data.quebra)
          const quantidade = retornarValorMonetarioEmFloat(data.quantidade)
          const valor = retornarValorItemComposicao({ custo, quantidade, quebra })

          if (!valor || isNaN(valor)) {
            row.data({ ...data, custo: 0, quantidade: 0, quebra: 0, valor: 0 })
          } else {
            row.data({ ...data, custo, quantidade, quebra, valor })
          }
          recalcularDadosTabelaComposicao()

          if (enterCampoCustoFoiPressionado) {
            $(`#txtQuebraComposicao${index}`).focus()
          }
        } catch { }
        finally {
          enterCampoCustoFoiPressionado = false
        }
      })

    let enterCampoQuebraFoiPressionado = false
    $(`#txtQuebraComposicao${index}`)
      .on('keydown', function (e) {
        enterCampoQuebraFoiPressionado = (e.key === 'Enter')
        if (enterCampoQuebraFoiPressionado) {
          e.preventDefault()
          $(this).blur()
        }
      }).on('blur', function () {
        try {
          const quebra = retornarValorMonetarioEmFloat(this.value)
          const data = row.data()
          const quantidade = retornarValorMonetarioEmFloat(data.quantidade)
          const custo = retornarValorMonetarioEmFloat(data.custo)
          const valor = retornarValorItemComposicao({ quebra, quantidade, custo })

          if (!valor || isNaN(valor)) {
            row.data({ ...data, custo: 0, quantidade: 0, quebra: 0, valor: 0 })
          } else {
            row.data({ ...data, custo, quantidade, quebra, valor })
          }
          recalcularDadosTabelaComposicao()

          if (enterCampoQuebraFoiPressionado) {
            $(`#txtCodigoComposicao${index + 1}`)?.focus()
          }
        } catch { }
        finally {
          enterCampoQuebraFoiPressionado = false
        }
      })
  }

  async function atualizarItemComposicaoComDadosDoCodigoInformado(codigo, index, row) {
    try {
      const {
        descricao,
        unidade,
        custo: custoBruto,
        atualizadoEm,
      } = await buscarDadosItemComposicaoInformado(codigo)

      const rowData = row.data()
      const quebra = retornarValorMonetarioEmFloat(rowData.quebra)
      const quantidade = retornarValorMonetarioEmFloat(rowData.quantidade)
      const custo = retornarValorMonetarioEmFloat(custoBruto)
      const valor = retornarValorItemComposicao({ custo, quebra, quantidade })
      const newData = {
        ...rowData,
        codigo,
        descricao,
        unidade,
        custo: retornarFloatFormatadoEmMonetario({ valor: custo, quantidadeCasasDecimais: 6 }),
        valor: retornarFloatFormatadoEmMonetario({ valor, quantidadeCasasDecimais: 6 }),
        atualizadoEm,
      }
      row.data(newData)
      recalcularDadosTabelaComposicao()
    } catch (error) {
      msgErro('Ocorreu um erro ao buscar os dados.')
      console.error(error)
    }
  }

  function retornarValorItemComposicao({ quantidade, custo, quebra }) {
    if (quebra >= 100) {
      quebra = 99.999999
    }
    return (quantidade * custo) / ((100 - quebra) / 100)
  }

  function adicionarEventosComposicao(table) {
    table.rows().every((index) => {
      const row = table.row(index)
      adicionarEventosBotoesComposicao(index, row)
      adicionarEventosInputsComposicao(index, row)
    })
  }

  async function buscarDadosItemComposicaoInformado(codigo) {
    const pesquisa = retornarPesquisaItemComposicao(codigo)
    const result = await retornaJsonPesquisaPadrao(JSON.stringify(pesquisa))
    return {
      descricao: result[0]?.DESCRICAO ?? '',
      unidade: result[0]?.UNIDADE ?? '',
      custo: result[0]?.CUSTO ?? 0,
      atualizadoEm: result[0]?.DT_ULT_ATUALIZACAO ?? '',
    }
  }

  $('#btnIncluirItemComposicao').on('click', function () {
    adicionarItemComposicao()
  })

  function adicionarItemComposicao(data) {
    let table = $('#tabelaComposicao').DataTable()
    if (!data) {
      const ordem = table.data().toArray().reduce((acc, item) => acc < item.ordem ? item.ordem : acc, 0) + 1
      const acumulado = table.data().toArray().reduce((acc, item) => acc += retornarValorMonetarioEmFloat(item.valor), 0)
      data = {
        ordem,
        codigo: '',
        descricao: '',
        unidade: '',
        quantidade: 0,
        custo: 0,
        quebra: 0,
        valor: 0,
        acumulado,
        atualizadoEm: '',
      }
    }
    table.row.add(data)
    const index = table.rows().count() - 1
    recalcularDadosTabelaComposicao()
    table = $('#tabelaComposicao').DataTable()
    const row = table.row(index)
    if (row.node()) {
      table.rows().deselect()
      row.select()
      setTimeout(() => {
        $(row.node()).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
      }, 150)
    }
  }

  function recalcularDadosTabelaComposicao() {
    const table = $('#tabelaComposicao').DataTable()
    const data = table.data().toArray()
    let acumulado = 0

    const novosDados = data.map((item, idx) => {
      const valor = retornarValorMonetarioEmFloat(item?.valor)
      acumulado += valor
      return {
        ...item,
        acumulado,
        ordem: idx + 1,
      }
    })

    criarTabelaComposicao(novosDados)
  }

  async function carregarComposicaoMaterial({ codigo, descricao, ordem }, idPreco) {
    $('#tituloModalComposicao').html(`[${codigo} - ${descricao}] - Composição`)
    $('#txtArtigoComposicao').val(codigo)
    $('#txtOrdemComposicao').val(ordem)
    const dadosComposicaoJaAdicionados = $('#tabelaComposicaoGravar').DataTable().data().toArray().filter((item) => item.codigoArtigo === codigo && item.ordemArtigo === ordem)
    if (dadosComposicaoJaAdicionados && dadosComposicaoJaAdicionados.length > 0) {
      criarTabelaComposicao(dadosComposicaoJaAdicionados)
      $('#modalComposicao').modal('show')
      return
    }

    $.LoadingOverlay('show')
    buscarComposicaoMaterial(idPreco, ordem, codigo)
      .then(({ aviamentos }) => {
        criarTabelaComposicao(aviamentos)
        $('#modalComposicao').modal('show')
      })
      .catch((error) => {
        console.error(error)
        msgErro('Ocorreu um erro ao carregar os dados.')
      })
      .finally(() => $.LoadingOverlay('hide'))
  }

  async function buscarComposicaoMaterial(idPreco, ordem, codigo) {
    const filtros = {
      idPreco,
      ordem,
      codigo,
    }
    const response = await requisicao("GET", `/sisplan/formacaocustos/v1/composicao?`, `FILTROS=${encodeURIComponent(JSON.stringify(filtros))}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado
    }
  }

  $('#btnConfirmarModalComposicao').on('click', function () {
    try {
      const ordem = safeParseInt($('#txtOrdemComposicao').val()) ?? 0
      const artigo = $('#txtArtigoComposicao').val()
      confirmarComposicao(ordem, artigo)
      $('#modalComposicao').modal('hide')
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao confirmar os dados.')
    }
  });

  function confirmarComposicao(ordemArtigo, codigoArtigo) {
    const dadosAlteracao = $('#tabelaComposicao').DataTable().data().toArray()
    const dadosGravar = $('#tabelaComposicaoGravar').DataTable().data().toArray().filter((item) => item.ordemArtigo !== ordemArtigo)
    dadosAlteracao.forEach((item) => {
      dadosGravar.push({ ...item, ordemArtigo, codigoArtigo, ultimaAtualizacao: item.ultimaAtualizacao ?? '1899-12-29' })
    })
    criarTabelaComposicaoGravar(dadosGravar)
    let tabelaItens = $('#tabelaItens').DataTable()
    const itens = tabelaItens.data().toArray()
    const item = itens.find((item) => item.codigo === codigoArtigo && item.ordem === ordemArtigo)
    const quantidade = retornarValorMonetarioEmFloat(item.quantidade)
    const custo = retornarValorMonetarioEmFloat($('#txtCustoTotalModalComposicao').val())
    const novoItem = {
      ...item,
      custo,
      valor: custo * quantidade,
    }
    const novosItens = itens.map((it) => {
      if (it.codigo === codigoArtigo && it.ordem === ordemArtigo) {
        return novoItem
      }

      return it
    })
    criarTabelaItens(novosItens)
    recarregarDadosItens()
    tabelaItens = $('#tabelaItens').DataTable()
    const linha = tabelaItens.row(indiceLinhaSelecionadaTabelaItens).node()
    setTimeout(() => {
      $(linha).get(0).scrollIntoView({ behavior: 'smooth', block: 'center' })
    }, 150)
  }

  criarTabelaComposicaoGravar()

  function criarTabelaComposicaoGravar(data = []) {
    if ($.fn.DataTable.isDataTable('#tabelaComposicaoGravar')) {
      $('#tabelaComposicaoGravar').DataTable().destroy()
      $('#tabelaComposicaoGravar').empty()
    }

    const columns = [
      {
        data: 'ordemArtigo',
        title: 'Ordem Artigo',
      },
      {
        data: 'ordem',
        title: 'Ordem',
      },
      {
        data: 'codigo',
        title: 'Código Artigo',
      },
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
      },
      {
        data: 'custo',
        title: 'Custo',
      },
      {
        data: 'quebra',
        title: 'Quebra',
      },
      {
        data: 'valor',
        title: 'Valor',
      },
      {
        data: 'acumulado',
        title: 'Acumulado',
      },
      {
        data: 'ultimaAtualizacao',
        title: 'Atualizado Em',
      },
    ]

    $("#tabelaComposicaoGravar").DataTable({
      info: false,
      order: false,
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
    })
  }

  criarTabelaComposicaoAlteracao()

  function criarTabelaComposicaoAlteracao(data = []) {
    if ($.fn.DataTable.isDataTable('#tabelaComposicaoAlteracao')) {
      $('#tabelaComposicaoAlteracao').DataTable().destroy()
      $('#tabelaComposicaoAlteracao').empty()
    }

    const columns = [
      {
        data: 'ordemArtigo',
        title: 'Ordem Artigo',
      },
      {
        data: 'ordem',
        title: 'Ordem',
      },
      {
        data: 'codigo',
        title: 'Código Artigo',
      },
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
      },
      {
        data: 'custo',
        title: 'Custo',
      },
      {
        data: 'quebra',
        title: 'Quebra',
      },
      {
        data: 'valor',
        title: 'Valor',
      },
      {
        data: 'acumulado',
        title: 'Acumulado',
      },
      {
        data: 'ultimaAtualizacao',
        title: 'Atualizado Em',
      },
    ]

    $("#tabelaComposicaoAlteracao").DataTable({
      info: false,
      order: false,
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      filter: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
    })
  }

  function atualizarItensComposicaoAposRemoverItem({ ordem }) {
    const itensComposicaoAtuais = $('#tabelaComposicaoAlteracao').DataTable().data().toArray()
    const novosItensComposicao = itensComposicaoAtuais
      .filter((item) => item.ordemArtigo !== ordem)
      .map((item) => {
        if (item.ordemArtigo > ordem) {
          return { ...item, ordemArtigo: item.ordemArtigo - 1 }
        }

        return item
      })

    criarTabelaComposicaoAlteracao(novosItensComposicao)
  }

  function atualizarItensComposicaoAposAlterarItem({ ordem }) {
    const itensComposicaoAtuais = $('#tabelaComposicaoAlteracao').DataTable().data().toArray()
    const novosItensComposicao = itensComposicaoAtuais
      .filter((item) => item.ordemArtigo !== ordem)

    criarTabelaComposicaoAlteracao(novosItensComposicao)
  }

  $('#tabelaComposicao').on('draw.dt', function () {
    const custoTotal = $('#tabelaComposicao').DataTable().data().toArray().reduce((acc, item) => acc + retornarValorMonetarioEmFloat(item.valor), 0)
    $('#txtCustoTotalModalComposicao').val(retornarFloatFormatadoEmMonetario({ valor: custoTotal, quantidadeCasasDecimais: 6 }))
  })

  $('#btnVoltar').on('click', function () {
    window.location.href = `${BASE_URI}/formacao_custos`
  })

  function criarTabelaConferenciaMaoDeObra(data, height) {
    if ($.fn.DataTable.isDataTable('#tabelaConferenciaMaoDeObra')) {
      $('#tabelaConferenciaMaoDeObra').DataTable().destroy()
      $('#tabelaConferenciaMaoDeObra').empty()
    }

    const columns = [
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'custo',
        title: 'Custo',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
      {
        data: 'valor',
        title: 'Valor',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return retornarFloatFormatadoEmMonetario({ valor: 0, quantidadeCasasDecimais: 6 })
          }
          return retornarFloatFormatadoEmMonetario({ valor: data, quantidadeCasasDecimais: 6 })
        },
      },
    ]

    $("#tabelaConferenciaMaoDeObra").DataTable({
      sort: false,
      paging: false,
      destroy: true,
      lengthChange: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
      scrollY: height ?? "295px",
      searching: true,
      filter: true,
    }).draw(false)

    const titleContainer = $('#tabelaConferenciaMaoDeObra_wrapper > div:first-child > div:first-child')
    titleContainer.addClass("flex align-items-end")
    titleContainer.html('<h5 class="pl-1">Mão de obra</h5>')
  }

  function carregarGraficoPercentualCusto() {
    if (graficoPercentualCustoTimeout) {
      clearTimeout(graficoPercentualCustoTimeout)
    }

    graficoPercentualCustoTimeout = setTimeout(() => {
      const itens = $('#tabelaItens').DataTable().data().toArray()
      const valorTotal = retornarValorMonetarioEmFloat($('#txtCustoTotal').val())
      const dadosGrafico = retornarDadosGraficoPercentualCusto(itens, valorTotal)

      GraficosFormacaoCustos.criarGraficoPizza({
        container: 'graficoPercentualCusto',
        data: dadosGrafico,
        grafico3d: true,
      })
    }, 1500)
  }

  function retornarDadosGraficoPercentualCusto(itens, valorTotal) {
    const valorTotalSeguro = valorTotal > 0 ? valorTotal : 1
    const itensAgrupados = []
    itens.forEach((item) => {
      const index = itensAgrupados.findIndex((it) => it.grupo === item.grupo)
      if (index > -1) {
        itensAgrupados[index].valor += retornarValorMonetarioEmFloat(item.valor)
      } else {
        itensAgrupados.push({
          grupo: item.grupo,
          descricaoGrupo: item.descricaoGrupo,
          valor: retornarValorMonetarioEmFloat(item.valor)
        })
      }
    })

    const dadosCalculados = itensAgrupados
      .filter((item) => item.valor > 0)
      .map((item) => {
        return {
          name: item.descricaoGrupo,
          y: (item.valor / valorTotalSeguro) * 100,
        }
      })

    return dadosCalculados
  }

  $('#btnFotoProduto').on('click', function () {
    const codigo = $('#txtCodigo').val()
    if (!codigo) {
      return
    }
    carregarFotoProduto(codigo)
    const prefixoTitulo = retornarPrefixoTitulosModais()
    const titulo = `${prefixoTitulo} - Foto Produto`
    $('#tituloModalFotoProduto').html(titulo)
  })

  function carregarFotoProduto(codigo) {
    $.LoadingOverlay('show')
    buscarFotoProduto(codigo).then((dados) => {
      if (!dados.fotoExiste) {
        $('#imagemProduto').attr('src', `${BASE_URI}/dist/img/prod-1.png`)
        msgErro('Foto não encontrada.')
        return
      }

      $('#imagemProduto').attr('src', `data:image/png;base64,${dados.base64}`)
      $('#modalFotoProduto').modal('show')
    }).catch((error) => {
      console.error(error)
      msgErro('Ocorreu um erro ao buscar a foto.')
    }).finally(() => $.LoadingOverlay('hide'))
  }

  async function buscarFotoProduto(codigo) {
    const response = await requisicao("GET", `/sisplan/formacaocustos/v1/fotoproduto?`, `CODIGO=${encodeURIComponent(codigo)}`, '', 3600000)

    const json = await response.json()

    if (json) {
      const { resultado, mensagem } = json
      if (mensagem?.codigo !== 200) {
        throw mensagem?.mensagem
      }

      return resultado
    }
  }

  $('#modalFotoProduto').on('hide.bs.modal', function () {
    $('#imagemProduto').attr('src', '')
  })

  $('#modalMarkup').on('hide.bs.modal', function () {
    $('.modalRowMarkup1').addClass('d-none')
    $('.modalRowMarkup2').addClass('d-none')
    $('.modalRowMarkup3').addClass('d-none')
    $('.modalRowMarkup4').addClass('d-none')
    $('.modalRowMarkup5').addClass('d-none')
    $('.modalRowMarkup6').addClass('d-none')
    $('.modalRowMarkup7').addClass('d-none')
  })

  $('#cbPadrao').on('change', async function () {
    if (!this.checked) {
      return
    }

    validarSeJaExisteCadastroPadrao()
  })

  async function validarSeJaExisteCadastroPadrao() {
    const produto = $('#txtCodigo').val()

    if (!produto) {
      return
    }

    const id = $('#txtIdPreco').val() || 0

    const pesquisa = {
      tabela: 'PRECO',
      camposSelect: ['1'],
      where: [`CODIGO = '${produto}'`, "PADRAO = 'S'", `ID <> ${id}`]
    }

    const [response] = await retornaJsonPesquisaPadrao(JSON.stringify(pesquisa))

    if (!response || response.length == 0) {
      return
    }

    msgAlerta(
      'Já existe um cadastro com esse código como padrão, deseja definir esse cadastro como padrão?',
      () => { },
      () => $('#cbPadrao').prop('checked', false),
      () => $('#cbPadrao').prop('checked', true),
      () => $('#cbPadrao').prop('checked', false),
      false,
      false,
      false,
      'Sim',
      'Não',
    )
  }
})