$(document).ready(async function () {
  componenteFiltro('deposito', false, false, 'DepositoBaixaConsumosFaccao')
  componenteFiltro('local', false, false, 'LocalBaixaConsumosFaccao')

  $('#formBaixaConsumosFaccao').validate({
    rules: {
      deposito: {
        required: true,
      },
    },
    messages: {
      deposito: 'Depósito é obrigatório.',
    },
    errorElement: 'span',
    errorPlacement(error, element) {
      error.addClass('invalid-feedback')
      element.closest('.form-group').append(error)
    },
    highlight(element) {
      $(element).addClass('is-invalid')
    },
    unhighlight(element) {
      $(element).removeClass('is-invalid')
    },
    submitHandler: async (_form, event) => {
      event.preventDefault()
    }
  })

  const resetForm = (formSelector) => {
    $(formSelector)[0].reset()
    const validator = $(formSelector).validate()
    validator.resetForm()
    $(formSelector)
      .find('.error')
      .removeClass('error')
  }

  $('#modalBaixaConsumosFaccao').on('hide.bs.modal', () => {
    limparModal()
    resetForm('#formBaixaConsumosFaccao')
  })

  const limparModal = () => $('.formBaixaConsumosFaccao').val('')

  $('#btnConfirmarBaixaConsumosFaccao').on('click', async () => {
    try {
      $.LoadingOverlay('show')
      const formValido = $('#formBaixaConsumosFaccao').valid()
      if (!formValido) {
        return
      }

      const dados = ModalBaixaConsumos.retornarDadosGravar()
      await ModalBaixaConsumos.gravar(dados)
    } catch (error) {
      console.error(error)
      msgErro('Não foi possível gravar os dados.')
    } finally {
      $.LoadingOverlay('hide')
    }
  })

  $('#txtDepositoBaixaConsumosFaccao').on('blur', async function () {
    try {
      const deposito = pegaChave(this)
      if (!deposito) {
        return
      }
      $.LoadingOverlay('show')

      const dados = await ModalBaixaConsumos.buscar(ModalBaixaConsumos.numero, ModalBaixaConsumos.parte, ModalBaixaConsumos.setor, deposito)
      ModalBaixaConsumos.carregar({ consumos: dados.consumos, estoque: dados.estoque })
    } finally {
      $.LoadingOverlay('hide')
    }
  })

  $('#btnFecharBaixaConsumosFaccao').on('click', function () {
    ModalBaixaConsumos.fechar(ModalBaixaConsumos.reject)
  })
})

window.ModalBaixaConsumos = window.ModalBaixaConsumos || {}

ModalBaixaConsumos.numero = null
ModalBaixaConsumos.lancamento = null
ModalBaixaConsumos.cliente = null
ModalBaixaConsumos.produto = null
ModalBaixaConsumos.parte = null
ModalBaixaConsumos.setor = null
ModalBaixaConsumos.resolve = () => { }
ModalBaixaConsumos.reject = () => { }

ModalBaixaConsumos.abrir = function () {
  $('#modalBaixaConsumosFaccao').modal('show')
}

ModalBaixaConsumos.fechar = function (callback) {
  $('#modalBaixaConsumosFaccao').modal('hide')
  callback?.()
}

ModalBaixaConsumos.gravar = async function (dados) {
  try {
    const response = await requisicao('POST', `/sisplan/consumosfaccao/v1/dados?`, '', JSON.stringify(dados), 3600000)
    const json = await response.json()

    if (!json) {
      return
    }

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

    criaMensagemSucesso(`Dados gravados com sucesso!`, () => {
      ModalBaixaConsumos.fechar(ModalBaixaConsumos.resolve)
    });
  } catch (error) {
    console.error(error)
    msgErro(error)
  }
}

ModalBaixaConsumos.buscar = async function (numero, parte, setor, deposito) {
  try {
    const response = await requisicao('GET', `/sisplan/consumosfaccao/v1/dados?`, `NUMERO=${numero}&PARTE=${parte}&SETOR=${setor}&DEPOSITO=${deposito}`, '', 3600000)
    const json = await response.json()

    if (!json) {
      return
    }

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

    return resultado
  } catch (error) {
    console.error(error)
    return null
  }
}

ModalBaixaConsumos.carregar = function ({ deposito, consumos, estoque, numero, cliente, lancamento, produto, parte, setor, resolve, reject }) {
  if (deposito?.codigo) {
    insereValor('#txtDepositoBaixaConsumosFaccao', deposito?.codigo, deposito?.descricao)
  }
  ModalBaixaConsumos.criarTabelaEstoque(estoque)
  ModalBaixaConsumos.criarTabelaConsumos(consumos)
  if (numero) {
    ModalBaixaConsumos.numero = numero
  }
  if (cliente) {
    ModalBaixaConsumos.cliente = cliente
  }
  if (lancamento) {
    ModalBaixaConsumos.lancamento = lancamento
  }
  if (produto) {
    ModalBaixaConsumos.produto = produto
  }
  if (parte) {
    ModalBaixaConsumos.parte = parte
  }
  if (setor) {
    ModalBaixaConsumos.setor = setor
  }
  if (resolve) {
    ModalBaixaConsumos.resolve = resolve
  }
  if (reject) {
    ModalBaixaConsumos.reject = reject
  }
}

ModalBaixaConsumos.criarTabelaConsumos = function (data) {
  if ($.fn.DataTable.isDataTable('#tabelaConsumosFaccao')) {
    $('#tabelaConsumosFaccao').DataTable().destroy()
    $('#tabelaConsumosFaccao').empty()
  }

  const columns = [
    {
      data: 'id',
      title: 'Id',
      visible: false,
    },
    {
      data: 'codigo',
      title: 'Código',
    },
    {
      data: 'descricao',
      title: 'Descrição',
    },
    {
      data: 'unidade',
      title: 'Unidade',
      visible: false,
    },
    {
      data: 'cor',
      title: 'Cor',
    },
    {
      data: 'descCor',
      title: 'Desc. Cor',
    },
    {
      data: 'aplicacao',
      title: 'Aplicação',
      visible: false,
    },
    {
      data: 'descAplicacao',
      title: 'Desc. Aplicação',
      visible: false,
    },
    {
      data: 'qtdeBaixar',
      title: 'Qtde Baixar',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
    },
    {
      data: 'consumo',
      title: 'Consumo',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'qtdeEstoque',
      title: 'Estoque',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
    },
    {
      data: 'baixado',
      title: 'Baixado',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
    },
    {
      data: 'qtdeReserva',
      title: 'Reservado',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
    },
    {
      data: 'lote',
      title: 'Lote',
      visible: false,
    },
    {
      data: 'qtde',
      title: 'Qtde',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
      visible: false,
    },
    {
      data: 'consumoOriginal',
      title: 'Consumo Orig.',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
      visible: false,
    },
    {
      data: 'totalReserva',
      title: 'Total Reserva',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
      visible: false,
    },
    {
      data: 'saldo',
      title: 'Saldo',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      },
      visible: false,
    },
    {
      data: 'setor',
      title: 'Setor',
      visible: false,
    },
    {
      data: 'descSetor',
      title: 'Desc. Setor',
      visible: false,
    },
    {
      data: 'parte',
      title: 'Parte',
      visible: false,
    },
  ]

  const table = $('#tabelaConsumosFaccao').DataTable({
    sort: false,
    paging: false,
    destroy: true,
    lengthChange: false,
    filter: false,
    info: false,
    ordering: false,
    sorting: false,
    order: false,
    autoWidth: true,
    data: data ?? [],
    columns,
    scrollX: true,
    scrollY: '30vh',
    select: {
      style: 'single',
      toggleable: false,
    },
  })

  let selectedRowIndex = 0

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

  table.off('select')
  table.on('select', function (_e, _dt, type, indexes) {
    if (type === 'row') {
      const data = table.rows(indexes[0]).data().toArray()
      const id = data?.[0]?.id

      const registrosFiltrados = $('#tabelaEstoqueConsumosFaccao').DataTable().column('idConsumo:name').search(`^${id}$|^$`, true, false);
      if (registrosFiltrados.length > 0) {
        registrosFiltrados.draw(false);
      };
    }
  })
  selectRow(selectedRowIndex)

  setTimeout(() => {
    table.columns.adjust()
  }, 300)
}

ModalBaixaConsumos.criarTabelaEstoque = function (data) {
  if ($.fn.DataTable.isDataTable('#tabelaEstoqueConsumosFaccao')) {
    $('#tabelaEstoqueConsumosFaccao').DataTable().destroy()
    $('#tabelaEstoqueConsumosFaccao').empty()
  }

  const columns = [
    {
      data: 'sel',
      title: 'Sel',
      render: (data, _type, _row, { row: rowIndex, col: colIndex }) => {
        const checked = data ? 'checked' : ''
        return (
          `<div class="icheck-primary d-inline">
          <input ${checked} type="checkbox" id="check_col_${colIndex}_row_${rowIndex}" class="checkSel">
          <label for="check_col_${colIndex}_row_${rowIndex}"></label>
        </div>`
        )
      }
    },
    {
      data: 'idConsumo',
      title: 'Id Consumo',
      name: 'idConsumo',
    },
    {
      data: 'codigo',
      title: 'Código',
    },
    {
      data: 'cor',
      title: 'Cor',
    },
    {
      data: 'deposito',
      title: 'Depósito',
    },
    {
      data: 'barra',
      title: 'Barra',
      visible: false,
    },
    {
      data: 'lote',
      title: 'Lote',
    },
    {
      data: 'qualidade',
      title: 'Qualidade',
      visible: false,
    },
    {
      data: 'qtde',
      title: 'Qtde',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'qtdeUtilizada',
      title: 'Qtde Utilizada',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'reservadoTotal',
      title: 'Reservado Total',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'saldoReserva',
      title: 'Disponível',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'consumo',
      title: 'Consumo',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'saldo',
      title: 'Saldo',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'qtdeBaixar',
      title: 'Qtde Baixar',
      className: 'text-right',
      render: function (data) {
        return data?.toFixed(4) ?? '0.0000'
      }
    },
    {
      data: 'local',
      title: 'Local',
      visible: false,
    },
    {
      data: 'entrada',
      title: 'Entrada',
      render(data) {
        return retornarDataISOEmYMD({ dataISO: data, usarUTC: true, reverso: true })
      },
      visible: false,
    },
    {
      data: 'obs',
      title: 'Obs',
      visible: false,
    },
  ]

  const table = $('#tabelaEstoqueConsumosFaccao').DataTable({
    sort: false,
    paging: false,
    destroy: true,
    lengthChange: false,
    filter: true,
    info: false,
    ordering: false,
    sorting: false,
    order: false,
    autoWidth: true,
    data: data ?? [],
    columns,
    scrollX: true,
    scrollY: '25vh',
  })

  $('#tabelaEstoqueConsumosFaccao').off('change', '.checkSel')
  $('#tabelaEstoqueConsumosFaccao').on('change', '.checkSel', function () {
    const isChecked = $(this).prop('checked')
    const row = table.row($(this).closest('tr'))
    const rowData = row.data()

    if (isChecked) {
      if (rowData.saldoReserva <= 0) {
        $(this).prop('checked', false)
        msgErro('Quantidade disponível zerada. Impossível continuar.')
        return
      }

      if (rowData.saldo === 0) {
        $(this).prop('checked', false)
        msgErro('Não há saldo para baixar. Impossível continuar.')
        return
      }

      ModalBaixaConsumos.recalcularQtdeAoSelecionar(rowData, table, row)
    } else {
      ModalBaixaConsumos.recalcularQtdeAoDeselecionar(rowData, table, row)
    }

    table.draw(false)
  })

  setTimeout(() => {
    table.columns.adjust()
  }, 300)
}

ModalBaixaConsumos.recalcularQtdeAoSelecionar = function (rowData, table, row) {
  rowData.sel = true
  if (rowData.saldo <= rowData.saldoReserva) {
    rowData.qtdeBaixar = rowData.saldo
  } else {
    rowData.qtdeBaixar = rowData.saldoReserva
  }

  let estoqueFiltrado = table.rows().indexes().filter(function (idx) {
    const data = table.row(idx).data()

    return data.codigo === rowData.codigo && data.cor === rowData.cor && data.lote === rowData.lote
  })

  estoqueFiltrado.each(function (idx) {
    const linhaIteracao = table.row(idx)
    const data = linhaIteracao.data()

    data.saldoReserva -= rowData.qtdeBaixar
    data.qtdeUtilizada += rowData.qtdeBaixar

    linhaIteracao.data(data)
  })

  estoqueFiltrado = table.rows().indexes().filter(function (idx) {
    const data = table.row(idx).data()

    return data.idConsumo === rowData.idConsumo
  })

  let qtdeBaixar = 0
  estoqueFiltrado.each(function (idx) {
    const data = table.row(idx).data()

    qtdeBaixar += data.qtdeBaixar
  })

  estoqueFiltrado.each(function (idx) {
    const linhaIteracao = table.row(idx)
    const data = linhaIteracao.data()

    data.saldo = Math.max(data.saldo - qtdeBaixar, 0)

    linhaIteracao.data(data)
  })

  row.data(rowData)
}

ModalBaixaConsumos.recalcularQtdeAoDeselecionar = function (rowData, table, row) {
  const qtdeBaixar = rowData.qtdeBaixar
  rowData.qtdeBaixar = 0
  rowData.sel = false

  let estoqueFiltrado = table.rows().indexes().filter(function (idx) {
    const data = table.row(idx).data()

    return data.codigo === rowData.codigo && data.cor === rowData.cor && data.lote === rowData.lote
  })

  estoqueFiltrado.each(function (idx) {
    const linhaIteracao = table.row(idx)
    const data = linhaIteracao.data()

    data.saldoReserva += qtdeBaixar
    data.qtdeUtilizada -= qtdeBaixar

    linhaIteracao.data(data)
  })

  estoqueFiltrado = table.rows().indexes().filter(function (idx) {
    const data = table.row(idx).data()

    return data.idConsumo === rowData.idConsumo
  })

  estoqueFiltrado.each(function (idx) {
    const linhaIteracao = table.row(idx)
    const data = linhaIteracao.data()

    data.saldo += qtdeBaixar

    linhaIteracao.data(data)
  })

  row.data(rowData)
}

ModalBaixaConsumos.retornarDadosGravar = function () {
  const consumos = $('#tabelaConsumosFaccao').DataTable().data().toArray()
  const estoque = $('#tabelaEstoqueConsumosFaccao').DataTable().data().toArray().filter((it) => !!it.sel)
  const numero = ModalBaixaConsumos.numero
  const cliente = ModalBaixaConsumos.cliente
  const local = pegaChave('#txtLocalBaixaConsumosFaccao')
  const lancamento = ModalBaixaConsumos.lancamento
  const produto = ModalBaixaConsumos.produto
  const deposito = pegaChave('#txtDepositoBaixaConsumosFaccao')

  return {
    consumos,
    estoque,
    numero,
    cliente,
    local,
    lancamento,
    produto,
    deposito,
  }
}