$('#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: "#formPrincipal",
        popover: {
          title: "Campos",
          description:
            "Aqui se encontram os campos essenciais para consultar e gravar as informações.",
          position: "bottom",
        },
      },
      {
        element: "#formAprovador",
        popover: {
          title: "Aprovadores",
          description:
            "Aqui se encontram os aprovadores do fluxo.",
          position: "bottom",
        },
      },
      {
        element: '#btnVoltar',
        popover: {
          title: 'Voltar',
          description: 'Aqui se encontra o botão para voltar à consulta.',
          position: 'bottom'
        }
      },
      {
        element: '#btnGravar',
        popover: {
          title: 'Gravar',
          description: 'Aqui se encontra o botão para gravar as informações.',
          position: 'bottom'
        }
      }
    ])
    driver.start()
  })
})

$(document).ready(async function () {
  const url = window.location.href
  const id = url.split('/')[url.split('/').length - 1]

  if (id && id !== 'create') {
    carregarCadastro({ id })
  } else {
    criarTabelaAprovadores({ data: [] })
  }

  $('.campoFloat').maskMoney({
    decimal: ".",
    thousands: "",
    precision: 2,
  })

  componenteFiltro('centroCusto', true, true)
  componenteFiltro('tipo', true, true)
  componenteFiltro('grupoMA', true, true, 'GrupoMaterial')
  componenteFiltro('grupoPA', true, true, 'GrupoProduto')
  componenteFiltro('grupoMA', true, true, 'GrupoServico')
  componenteFiltro('subGrupo', true, true, 'SubgrupoMaterial')

  $('#txtAprovador').autocompleta(
    1,
    `JSON={ "tabela":"ACESSO_USUARIOS", "camposSelect":["CODIGO CHAVE", "NOME DESCRICAO", "ID"], "where": ["ATIVO = 'S'"] }`,
    ['#txtAprovador', '#txtIdAprovador'],
    ['CHAVE', 'ID'],
    ['DESCRICAO', 'ID'],
    undefined,
    [false, true]
  )
  $('#btnAprovador').pesquisa_serverside(
    ['#txtAprovador', '#txtIdAprovador'],
    ['CODIGO', 'ID'],
    ['NOME', 'ID'],
    `{ "tabela":"ACESSO_USUARIOS", "camposSelect":["CODIGO", "NOME", "ID"], "where": ["ATIVO = 'S'"] }`,
    'Pesquisa de Aprovadores',
    undefined,
    [false, true]
  )
  $('#btnLimpaAprovador').on('click', function () {
    $('#txtAprovador').val('')
    $('#txtIdAprovador').val('')
  })

  async function buscarDados({ id }) {
    const response = await requisicao('GET', `/sisplan/fluxo_aprovacao_compras/v1/retornardadoscadastro?`, `&ID=${id}`, '', 3600000)
    const json = await response.json()

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

      return resultado
    }
  }

  function carregarCadastro({ id }) {
    buscarDados({ id }).then((dados) => {
      const { aprovadores, ...capa } = dados
      preencherDadosCapa({ capa })
      criarTabelaAprovadores({ data: aprovadores })
    })
  }

  function preencherDadosCapa({ capa }) {
    if (!capa) return
    $('#txtId').val(capa.id)
    $('#txtDescricao').val(capa.descricao)
    $('#selectEtapa').val(capa.etapa)
    $('#txtValorMinimo').val(parseFloat(capa.valorMinimo).toFixed(2))
    $('#txtValorMaximo').val(parseFloat(capa.valorMaximo).toFixed(2))
    if (capa.centrosCusto) capa.centrosCusto.forEach((item) => adicionaValorPadraoVarios('centroCusto', item?.codigo, item?.descricao))
    if (capa.tipos) capa.tipos.forEach((item) => adicionaValorPadraoVarios('tipo', item?.codigo, item?.descricao))
    if (capa.gruposMaterial) capa.gruposMaterial.forEach((item) => adicionaValorPadraoVarios('grupoMaterial', item?.codigo, item?.descricao))
    if (capa.gruposProduto) capa.gruposProduto.forEach((item) => adicionaValorPadraoVarios('grupoProduto', item?.codigo, item?.descricao))
    if (capa.gruposServico) capa.gruposServico.forEach((item) => adicionaValorPadraoVarios('grupoServico', item?.codigo, item?.descricao))
    if (capa.subgruposMaterial) capa.subgruposMaterial.forEach((item) => adicionaValorPadraoVarios('subgrupoMaterial', item?.codigo, item?.descricao))
  }

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

    const columns = [
      {
        data: 'idUsuario',
        title: 'Id Usuário',
        visible: false,
      },
      {
        data: 'ordem',
        title: 'Ordem',
        render: function (data) {
          return '<div style="text-align:start;"> ' +
            '    <button class="btn btn-info btn-sm dropdown-toggle btnVerificaOpcoes" id="tutorialTabela" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> ' +
            '      ' + data + ' ' +
            '    </button> ' +
            '    <div class="dropdown-menu"> ' +
            '    <button class="dropdown-item" type="button" title="Alterar" id="btnAlterar">Alterar</button>     ' +
            '    <button class="dropdown-item" type="button" title="Excluir" id="btnExcluir">Excluir</button>  ' +
            '</div>'
        }
      },
      {
        data: 'codigoUsuario',
        title: 'Código Aprovador',
        visible: false,
      },
      {
        data: 'nomeUsuario',
        title: 'Nome Aprovador',
      },
    ]

    $('#tabelaAprovadores').DataTable({
      sort: false,
      paging: true,
      destroy: true,
      lengthChange: false,
      filter: false,
      info: false,
      ordering: false,
      sorting: false,
      order: false,
      autoWidth: true,
      data,
      columns,
      scrollX: true,
      scrollY: '150px',
    })
    setTimeout(() => {
      $('#tabelaAprovadores').DataTable().columns.adjust().draw(false)
    }, 300)
  }

  $('#tabelaAprovadores').on('click', '#btnExcluir', async function () {
    const datatable = $('#tabelaAprovadores').DataTable()
    const linha = $(this).parents('tr')
    const dados = datatable.row(linha).data()
    if (!dados) return
    excluirAprovador({ codigo: dados.codigo, tabela: datatable, linha })
    recalcularOrdem()
  })

  const excluirAprovador = ({ tabela, linha }) => {
    tabela.row(linha).remove().draw(false)
  }

  $('#formPrincipal').validate({
    rules: {
      descricao: {
        required: true,
      },
      etapa: {
        required: true,
      },
      valorMaximo: {
        required: true,
        maximoMaiorQueMinimo: true,
      },
      centroCusto: {
        required: true,
      },
      tipo: {
        required: true,
      },
    },
    messages: {
      descricao: 'Descrição é obrigatória.',
      etapa: 'Estágio é obrigatório.',
      valorMaximo: {
        required: 'Valor máximo é obrigatório.',
        maximoMaiorQueMinimo: 'O valor máximo deve ser maior que o valor mínimo.',
      },
      centroCusto: 'Centro de custo é obrigatório.',
      tipo: 'Tipo é 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 quantidadeAprovadores = $('#tabelaAprovadores').DataTable().data().toArray().length
      if (!quantidadeAprovadores || quantidadeAprovadores === 0) {
        msgErro('Nenhum aprovador informado, impossível continuar.')
        return
      }
      gravar()
    }
  })

  $.validator.addMethod('maximoMaiorQueMinimo', function (value) {
    const valorMinimo = parseFloat($('#txtValorMinimo').val() || 0)
    const valorMaximo = parseFloat(value)
    return valorMaximo > valorMinimo
  }, 'O valor máximo deve ser maior que o valor mínimo.')

  $('#formAprovador').validate({
    rules: {
      aprovador: {
        required: true,
      },
    },
    messages: {
      aprovador: 'Aprovador é 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 aprovador = {
        codigo: pegaChave('#txtAprovador'),
        descricao: pegaDescricao('#txtAprovador'),
        id: $('#txtIdAprovador').val(),
      }
      const edicao = $('#tabelaAprovadores tbody tr.selected').length > 0
      if (!edicao) {
        if (!validarAdicionarAprovador({ aprovador })) {
          return
        }
        adicionarAprovador({ aprovador })
      }
      else {
        if (!validarEditarAprovador({ aprovador })) {
          return
        }
        editarAprovador({ aprovador })
      }
      limparCamposAprovador()
      desabilitarEdicaoAprovador()
      $('.controleAprovador').prop('disabled', true)
    }
  })

  const validarAdicionarAprovador = ({ aprovador }) => {
    if ($('#tabelaAprovadores')
      .DataTable()
      .data()
      .toArray()
      .some((item) => item.idUsuario === aprovador.id)
    ) {
      msgErro('Aprovador já existe para o fluxo, impossível continuar.')
      return false
    }

    return true
  }

  const validarEditarAprovador = ({ aprovador }) => {
    const tabela = $('#tabelaAprovadores').DataTable()
    const [linhaSelecionada] = $('#tabelaAprovadores tbody tr.selected').toArray()
    const dadosTabela = tabela.data().toArray().filter((_, index) => tabela.row(linhaSelecionada).index() !== index)
    if (dadosTabela.some((item) => item.idUsuario === aprovador.id)) {
      msgErro('Aprovador já existe para o fluxo, impossível continuar.')
      return false
    }

    return true
  }

  const adicionarAprovador = ({ aprovador }) => {
    try {
      const datatable = $('#tabelaAprovadores').DataTable()
      const datatableData = datatable.data().toArray()
      const maiorOrdemAtual = datatableData.reduce((max, obj) => {
        return obj.ordem > max ? obj.ordem : max
      }, 0)
      const idUsuario = $('#txtIdAprovador').val()
      const dadosLinha = {
        ordem: maiorOrdemAtual + 1,
        idUsuario,
        codigoUsuario: aprovador.codigo,
        nomeUsuario: aprovador.descricao,
      }

      datatable.row.add(dadosLinha).draw(false)
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao adicionar o aprovador.')
    }
  }

  const limparCamposAprovador = () => $('#formAprovador input').val('')

  $('#tabelaAprovadores').on('click', 'tr', function () {
    if (!$('#btnConfirmarAprovador').hasClass('d-none')) {
      return
    }
    $('#tabelaAprovadores tbody tr').removeClass('selected')
    $(this).addClass('selected')
  })

  $('#tabelaAprovadores').on('click', '#btnAlterar', async function () {
    $('#tabelaAprovadores tbody tr').removeClass('selected')
    $(this).closest('tr').addClass('selected')
    const data = $('#tabelaAprovadores').DataTable().row($(this).parents('tr')).data()
    if (!data) return
    preencherCamposAprovador({ data })
    habilitarEdicaoAprovador()
  })

  const preencherCamposAprovador = ({ data }) => {
    insereValor('#txtAprovador', data.codigoUsuario, data.nomeUsuario)
    $('#txtIdAprovador').val(data.idUsuario)
  }

  const editarAprovador = ({ aprovador }) => {
    try {
      const tabela = $('#tabelaAprovadores').DataTable()
      const [linhaSelecionada] = $('#tabelaAprovadores tbody tr.selected').toArray()
      if (!linhaSelecionada) return
      const dadosTabela = tabela.row(linhaSelecionada).data()
      const idUsuario = $('#txtIdAprovador').val()

      const dadosAtualizados = {
        ...dadosTabela,
        idUsuario,
        codigoUsuario: aprovador.codigo,
        nomeUsuario: aprovador.descricao,
      }

      tabela.row(linhaSelecionada).data(dadosAtualizados).draw(false)
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao editar o item.')
    }
  }

  const retornarDadosGravar = async () => {
    const id = $('#txtId').val()
    const descricao = $('#txtDescricao').val()
    const valorMinimo = $('#txtValorMinimo').val() || 0
    const valorMaximo = $('#txtValorMaximo').val()
    const etapa = $('#selectEtapa').val()
    const centrosCusto = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtCentroCusto').val().toString()))
    const tipos = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtTipo').val().toString()))
    const gruposMaterial = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtGrupoMaterial').val().toString()))
    const gruposProduto = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtGrupoProduto').val().toString()))
    const gruposServico = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtGrupoServico').val().toString()))
    const subgruposMaterial = tratarMaximoCaracteresArrayString(300, await formataListas($('#txtSubgrupoMaterial').val().toString()))

    const aprovadores = $('#tabelaAprovadores').DataTable().data().toArray()
    return {
      id,
      descricao,
      valorMinimo,
      valorMaximo,
      etapa,
      centrosCusto,
      tipos,
      gruposMaterial,
      gruposProduto,
      gruposServico,
      subgruposMaterial,
      aprovadores,
    }
  }

  const gravar = async () => {
    $.LoadingOverlay('show')
    const dados = await retornarDadosGravar()
    enviarDadosGravar({ dados })
      .then(() => {
        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() {
            window.location.href = `${BASE_URI}/fluxo_aprovacao_compras`
          },
        }).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'))
  }

  const enviarDadosGravar = async ({ dados }) => {
    const response = await requisicao('POST', `/sisplan/fluxo_aprovacao_compras/v1/gravar?`, '', JSON.stringify(dados), 3600000)
    const json = await response.json()

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

  $('#tabelaAprovadores').on('click', '#btnExcluir', async function () {
    const datatable = $('#tabelaAprovadores').DataTable()
    const linha = $(this).parents('tr')
    const dados = datatable.row(linha).data()
    if (!dados) return
    excluirItem({ tipo: 'M', tabela: datatable, linha })
  })

  const excluirItem = ({ tabela, linha }) => {
    tabela.row(linha).remove().draw(false)
  }

  $('#btnIncluirAprovador').on('click', () => {
    habilitarEdicaoAprovador()
    $('#tabelaAprovadores tbody tr').removeClass('selected')
  })
  $('#btnDesistirAprovador').on('click', () => desabilitarEdicaoAprovador())

  const habilitarEdicaoAprovador = () => {
    $('.controleAprovador').prop('disabled', false)
    $('#btnIncluirAprovador').addClass('d-none')
    $('#btnConfirmarAprovador').removeClass('d-none')
    $('#btnDesistirAprovador').removeClass('d-none')
  }

  const desabilitarEdicaoAprovador = () => {
    $('.controleAprovador').prop('disabled', true)
    $('#btnIncluirAprovador').removeClass('d-none')
    $('#btnConfirmarAprovador').addClass('d-none')
    $('#btnDesistirAprovador').addClass('d-none')
    $('#txtAprovador').val('')
    $('#txtIdAprovador').val('')
    $('#tabelaAprovadores tbody tr').removeClass('selected')
  }

  const recalcularOrdem = () => {
    const dadosTabela = $('#tabelaAprovadores').DataTable().data().toArray()
    const dadosComOrdemRecalculada =
      dadosTabela
        .map((item) => {
          return {
            ...item,
            ordem: dadosTabela.indexOf(item) + 1,
          }
        })

    criarTabelaAprovadores({ data: dadosComOrdemRecalculada })
  }

  function tratarMaximoCaracteresArrayString(maximoCaracteres, texto) {
    if (texto.length <= maximoCaracteres) {
      return texto
    }

    const textoLimitado = texto.slice(0, maximoCaracteres)
    if (textoLimitado.slice(-1) === "'") {
      return textoLimitado
    }

    const array = textoLimitado.split(',')
    array.pop()

    return array.join(',')
  }

  $('#btnSubirOrdem').on('click', function () {
    try {
      const datatable = $('#tabelaAprovadores').DataTable()
      const selectedRow = datatable.rows('.selected')
      if (selectedRow.length > 1) {
        throw new Error()
      }
      alterarOrdemLinhaParaCima(datatable, selectedRow)
    } catch (error) {
      console.error(error)
      $('#tabelaProcessos').DataTable().rows().deselect()
    }
  })

  function alterarOrdemLinhaParaCima(datatable, selectedRow) {
    const [index] = selectedRow.indexes().toArray()
    if (index === undefined || index === null) {
      msgErro('Nenhuma linha selecionada, impossível continuar.')
      return
    }
    if (index <= 0) {
      return
    }
    const previousRowData = datatable.row(index - 1).data()
    const currentRowData = datatable.row(index).data()
    datatable.row(index - 1).data({ ...currentRowData, ordem: parseInt(currentRowData.ordem) - 1 })
    datatable.row(index).data({ ...previousRowData, ordem: parseInt(previousRowData.ordem) + 1 })
    datatable.rows().deselect()
    datatable.row(index - 1).select()
  }

  $('#btnDescerOrdem').on('click', function () {
    try {
      const datatable = $('#tabelaAprovadores').DataTable()
      const selectedRow = datatable.rows('.selected')
      if (selectedRow.length > 1) {
        throw new Error()
      }
      alterarOrdemLinhaParaBaixo(datatable, selectedRow)
    } catch (error) {
      console.error(error)
      $('#tabelaAprovadores tbody tr').removeClass('selected')
    }
  })

  function alterarOrdemLinhaParaBaixo(datatable, selectedRow) {
    const [index] = selectedRow.indexes().toArray()
    if (index === undefined || index === null) {
      msgErro('Nenhuma linha selecionada, impossível continuar.')
      return
    }
    if (index >= datatable.rows().count() - 1) {
      return
    }
    const previousRowData = datatable.row(index + 1).data()
    const currentRowData = datatable.row(index).data()
    datatable.row(index + 1).data({ ...currentRowData, ordem: parseInt(currentRowData.ordem) + 1 })
    datatable.row(index).data({ ...previousRowData, ordem: parseInt(previousRowData.ordem) - 1 })
    datatable.rows().deselect()
    datatable.row(index + 1).select()
  }

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