$('#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: '#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 () {
  $('.campoValor').maskMoney({
    decimal: ',',
    thousands: '',
    precision: 2
  });

  const permissaoUsuarioLogado = await permissaoAcessos('BAIXA_ORDEM_COMPRA')
  let colunas = JSON.parse(localStorage.getItem("colunasInvisiveisRelatorios"))

  if (colunas == null || colunas.baixaOrdemCompra == undefined) {
    localStorage.setItem(
      "colunasInvisiveisRelatorios",
      JSON.stringify({ ...colunas, baixaOrdemCompra: [] })
    )
    colunas = JSON.parse(localStorage.getItem("colunasInvisiveisRelatorios"))
  }

  $("#btnConfirmarColunas").on("click", async function () {
    try {
      $.LoadingOverlay("show")

      const novasColunas = retornaNovasColunasInvisiveis()

      localStorage.setItem(
        "colunasInvisiveisRelatorios",
        JSON.stringify({ ...colunas, baixaOrdemCompra: novasColunas })
      )

      $("#tabelaItens").DataTable().columns().visible(true)

      $("#tabelaItens")
        .DataTable()
        .columns()
        .every(function () {
          if (novasColunas.indexOf(this.dataSrc()) !== -1) {
            this.visible(false)
          }
        })
    } finally {
      $.LoadingOverlay("hide")
      $("#modal-ColunasVisiveis").modal("hide")
    }
  })

  componenteFiltro('ordemCompraBaixa', true, true, 'Numeros', [`EXISTS (SELECT 1 FROM [CO_ITEN] CO_ITEN WHERE COMPRA.NUMERO = CO_ITEN.NUMERO AND CO_ITEN.SITUACAO <> 'B' AND COMPRA.EMPRESA = '${getCookie('empresa').replace('_', '')}')"`])
  componenteFiltro('itensCompra', true, true, 'Codigos')
  componenteFiltro('cor', true, true, 'Cores')
  componenteFiltro('deposito', false, false)
  componenteFiltro('funcionario', false, false)
  componenteFiltro('tipoMov', false, false, 'TipoMovimento')

  carregarValoresPadroes()

  function carregarValoresPadroes() {
    buscaValoresPadroes('BAIXA_ORDEM_COMPRA').then((resultado) => {
      resultado.forEach((item) => {
        switch (item.CAMPO) {
          case 'DEPOSITO':
            insereValor('#txtDeposito', item.VALOR, {
              tabela: 'DEPOSITO',
              campoBusca: 'DESCRICAO',
              campoWhere: 'CODIGO',
              valorWhere: item.VALOR,
            })
            break
          case 'FUNCIONARIO':
            insereValor('#txtFuncionario', item.VALOR, {
              tabela: 'ENTIDADE',
              campoBusca: 'NOME',
              campoWhere: 'CODCLI',
              valorWhere: item.VALOR,
            })
            break
          case 'TIPO_MOVIMENTO':
            insereValor('#txtTipoMovimento', item.VALOR, {
              tabela: 'TABBAI',
              campoBusca: 'DESCRICAO',
              campoWhere: 'CODIGO',
              valorWhere: item.VALOR,
            })
            break
        }
      })
    })
  }

  $('#btnConsultar').on('click', async function () {
    consultar()
    $('#divQtdeBipada').removeClass('d-none')
  })

  async function consultar() {
    $.LoadingOverlay('show')
    const filtros = await retornarFiltros()
    buscarDados({ filtros }).then((resultado) => {
      if (!resultado) {
        msgErro('Nenhum registro encontrado.')
        return
      }

      const { itens } = resultado
      criarTabelaItens({ data: itens })
    }).catch((error) => {
      console.error(error)
      msgErro('Ocorreu um erro ao buscar os dados.')
    }).finally(() => {
      $.LoadingOverlay('hide')
    })
  }

  async function buscarDados({ filtros }) {
    const response = await requisicao('POST', `/sisplan/baixa_ordem_compra/v1/compras?`, '', JSON.stringify(filtros), 3600000)
    const json = await response.json()

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

      return resultado
    }
  }

  async function retornarFiltros() {
    const numeros = await formataListas($('#txtNumeros').val().toString())
    const codigos = await formataListas($('#txtCodigos').val().toString())
    const cores = await formataListas($('#txtCores').val().toString())
    const situacao = $('#selectSituacao').val()
    const percentual = $('#txtPercentual').val().replaceAll(',', '.')
    const dataEntrega = $('#txtEntrega').val() || '1200-01-01'

    return {
      numeros,
      codigos,
      cores,
      situacao,
      percentual,
      dataEntrega,
    }
  }

  const retornarDadosBaixar = async () => {
    const itens = $('#tabelaItens').DataTable().data().toArray().filter((item) => item.sel)
    const deposito = pegaChave('#txtDeposito')
    const funcionario = pegaChave('#txtFuncionario')
    const tipo = pegaChave('#txtTipoMovimento')
    const lote = $('#txtLote').val()
    const observacao = $('#txtObservacao').val()

    return {
      itens,
      deposito,
      funcionario,
      tipo,
      lote,
      observacao,
    }
  }

  function validarDadosBaixar({ itens, deposito }) {
    if (!itens || itens.length === 0) {
      msgErro('Nenhum item selecionado, impossível continuar.')
      return false
    }

    if (itens.some((item) => item.quantidadeBaixar > item.saldo)) {
      msgErro('Existe(m) item(ns) com quantidade a baixar maior que o saldo, impossível continuar.')
      return false
    }

    if (itens.some((item) => item.situacao === 'B')) {
      msgErro('Existe(m) item(ns) com ordem de compra totalmente baixada, impossível continuar.')
      return false
    }

    if (itens.some((item) => item.quantidadeBaixar <= 0)) {
      msgErro('Existe(m) item(ns) com quantidade a baixar menor ou igual a zero, impossível continuar.')
      return false
    }

    if (!deposito) {
      msgErro('Depósito não informado, impossível continuar')
      return false
    }

    return true
  }

  const baixar = async () => {
    if (!$.fn.DataTable.isDataTable('#tabelaItens')) {
      msgErro('Nenhum registro consultado, impossível continuar.')
      return
    }
    const dados = await retornarDadosBaixar()
    if (!validarDadosBaixar(dados)) {
      return
    }
    $.LoadingOverlay('show')
    enviarDadosBaixar({ 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() {
            $('#txtNumeros').empty().trigger('change')
            criarTabelaItens({ data: [] })
          },
        }).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 enviarDadosBaixar = async ({ dados }) => {
    const response = await requisicao('POST', `/sisplan/baixa_ordem_compra/v1/baixas?`, '', JSON.stringify(dados), 3600000)
    const json = await response.json()

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

  const retornarDadosEstornar = async () => {
    const itens = $('#tabelaItens').DataTable().data().toArray().filter((item) => item.sel)
    const deposito = pegaChave('#txtDeposito')
    const funcionario = pegaChave('#txtFuncionario')
    const tipo = pegaChave('#txtTipoMovimento')
    const lote = $('#txtLote').val()
    const observacao = $('#txtObservacao').val()

    return {
      itens,
      deposito,
      funcionario,
      tipo,
      lote,
      observacao,
    }
  }

  function validarDadosEstornar({ itens, deposito }) {
    if (!itens || itens.length === 0) {
      msgErro('Nenhum item selecionado, impossível continuar.')
      return false
    }

    if (itens.some((item) => item.quantidadeEstornar > item.quantidadeBaixada)) {
      msgErro('Existe(m) item(ns) com quantidade a estornar maior que a quantidade baixada, impossível continuar.')
      return false
    }

    if (itens.some((item) => item.quantidadeEstornar <= 0)) {
      msgErro('Existe(m) item(ns) com quantidade a estornar menor ou igual a zero, impossível continuar.')
      return false
    }

    if (!deposito) {
      msgErro('Depósito não informado, impossível continuar')
      return false
    }

    return true
  }

  const estornar = async () => {
    if (!$.fn.DataTable.isDataTable('#tabelaItens')) {
      msgErro('Nenhum registro consultado, impossível continuar.')
      return
    }
    const dados = await retornarDadosEstornar()
    if (!validarDadosEstornar(dados)) {
      return
    }
    $.LoadingOverlay('show')
    enviarDadosEstornar({ 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() {
            consultar()
          },
        }).css({
          "margin-top": "20%",
          width: "500px",
          "max-width": "500px",
        })
      })
      .catch((error) => {
        console.error(error)
        msgErro(error)
      })
      .finally(() => $.LoadingOverlay('hide'))
  }

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

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

  $('#tabelaItens').on('click', '#btnAlterar', async function () {
    if (permissaoUsuarioLogado.ALTERA !== 'S') {
      msgErro('Sem permissão para alterar!')
      return
    }
    const datatable = $('#tabelaItens').DataTable()
    const linha = datatable?.row($(this)?.parents('tr'))
    const dados = linha?.data()
    linha?.select()

    let valorNumerico = Number(dados.quantidadeBaixar)
    let valorFormatado = '0,00'
    if (!isNaN(valorNumerico)) {
      valorFormatado = valorNumerico
    }

    $('#txtQuantidadeBaixarModal').val(valorFormatado?.toLocaleString('pt-BR', {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    }))

    valorNumerico = Number(dados.quantidadeEstornar)
    valorFormatado = '0,00'
    if (!isNaN(valorNumerico)) {
      valorFormatado = valorNumerico
    }

    $('#txtQuantidadeEstornarModal').val(valorFormatado?.toLocaleString('pt-BR', {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    }))

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

  $('#btnBaixar').on('click', () => {
    if (permissaoUsuarioLogado.ALTERA !== 'S') {
      msgErro('Sem permissão para alterar!')
      return
    }
    msgAlerta(
      'Deseja realmente gravar os dados?',
      () => { },
      () => { },
      () => {
        baixar()
      },
    )
  })

  $('#btnEstornar').on('click', () => {
    if (permissaoUsuarioLogado.ALTERA !== 'S') {
      msgErro('Sem permissão para alterar!')
      return
    }
    msgAlerta(
      'Deseja realmente gravar os dados?',
      () => { },
      () => { },
      () => {
        estornar()
      },
    )
  })

  function criarTabelaItens({ data }) {
    if ($.fn.DataTable.isDataTable('#tabelaItens')) {
      $('#tabelaItens').DataTable().destroy()
      $('#tabelaItens').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: 'id',
        title: 'Id',
        render: function (data, _type) {
          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>
            </div>`
        }
      },
      {
        data: 'numero',
        title: 'Número',
      },
      {
        data: 'codigo',
        title: 'Código',
      },
      {
        data: 'descricao',
        title: 'Descrição',
      },
      {
        data: 'cor',
        title: 'Cor',
      },
      {
        data: 'descricaoCor',
        title: 'Descrição Cor',
      },
      {
        data: 'tamanho',
        title: 'Tamanho',
      },
      {
        data: 'dataEntrega',
        title: 'Entrega',
        render(data) {
          return new Intl.DateTimeFormat('pt-BR').format(new Date(`${data.split('T')?.[0]} 23: 59: 59`))
        },
      },
      {
        data: 'quantidade',
        title: 'Quantidade',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          return data.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'quantidadeBaixada',
        title: 'Quantidade Baixada',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          return data.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'quantidadeBaixar',
        title: 'Quantidade Baixar',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          const valorNumerico = Number(data)

          if (isNaN(valorNumerico)) {
            return '0,00'
          }

          return valorNumerico.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'quantidadeEstornar',
        title: 'Quantidade Estornar',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          const valorNumerico = Number(data)

          if (isNaN(valorNumerico)) {
            return '0,00'
          }

          return valorNumerico.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'quantidadeEstornada',
        title: 'Quantidade Estornada',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          return data.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'saldo',
        title: 'Saldo',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          return data.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'situacao',
        title: 'Situação',
      },
      {
        data: 'preco',
        title: 'Preço',
        className: 'text-right',
        render: function (data) {
          if (!data) {
            return '0,00'
          }
          return data.toLocaleString('pt-BR', {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          })
        }
      },
      {
        data: 'unidade',
        title: 'Unidade',
      },
      {
        data: 'unidadeCompra',
        title: 'Unidade de Compra',
      },
      {
        data: 'tipoItem',
        title: 'Tipo',
      },
    ]

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

    const colunasInvisiveis = JSON.parse(
      localStorage.getItem("colunasInvisiveisRelatorios")
    )

    $("#tabelaItens_length").prepend(
      '<button type="button" class="buttonColVis" id="buttonColVis"><i class="fas fa-cogs"></i></button>'
    )
    $("#tabelaItens_length").prepend(
      '<button type="button" class="buttonExcel ml-0" id="buttonExcel"><i class="fas fa-file-excel"></i></button>'
    )

    $("#buttonColVis").on("click", async function () {
      $.LoadingOverlay("show")
      $("#modal-ColunasVisiveis").modal("show")
      $.LoadingOverlay("hide")
    })

    $("#buttonExcel").on("click", async function () {
      const itens = structuredClone($('#tabelaItens').DataTable().data().toArray())
      await exportaCSV(
        '',
        '',
        false,
        null,
        "Relatório de Baixa de Ordem de Compra",
        "#tabelaItens",
        '',
        999,
        false,
        false,
        itens,
      )
    })

    $("#buttonColVis").prop("title", "Configurar colunas")
    $("#buttonExcel").prop("title", "Exportar CSV")

    $("#tabelaItens")
      .DataTable()
      .columns()
      .every(function () {
        if (
          colunasInvisiveis.baixaOrdemCompra.indexOf(this.dataSrc()) != -1
        ) {
          this.visible(false)
        }
      })

    $('#cbSelAll').off('click')
    $('#cbSelAll').on('click', function () {
      const isChecked = $(this).prop('checked')
      table.rows().every(function () {
        const rowData = this.data()
        const rowIndex = this.index()
        const inputCheckbox = $(this.node()).find('.checkSel')
        $(inputCheckbox).prop('checked', isChecked)
        rowData.sel = isChecked
        table.row(rowIndex).data(rowData)
      })
      table.draw(false)
    })

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

    atualizaTotais()
  }

  function atualizaTotais() {
    const qtdeBaixada = $("#tabelaItens").DataTable().column(10, {}).data().sum();
    const qtdeTotal = $("#tabelaItens").DataTable().column(9, {}).data().sum() - qtdeBaixada;
    const qtdeBaixar = $("#tabelaItens").DataTable().column(11, {}).data().sum();
    const qtdeEstornar = $("#tabelaItens").DataTable().column(12, {}).data().sum();

    const qtdeSaldo = qtdeTotal - qtdeBaixar - qtdeEstornar;


    $('#txtQuantidadeBipada').val(qtdeBaixar);
    $('#txtQuantidadeTotalOrdem').val(qtdeTotal);
    $('#txtQuantidadeSaldo').val(qtdeSaldo);
  }

  $("#modal-ColunasVisiveis").on("show.bs.modal", function () {
    const cols = []

    let colunasInvisiveis = JSON.parse(
      localStorage.getItem("colunasInvisiveisRelatorios")
    )
    $("#tabelaItens")
      .DataTable()
      .columns()
      .every(function () {
        if (['sel', 'id'].includes(this.dataSrc())) {
          return
        }
        cols.push({
          title: $(this.header()).text(),
          data: this.dataSrc(),
        })
      })
    adicionaColunas(cols, colunasInvisiveis.baixaOrdemCompra ?? [])
  })

  $('#btnConfirmarModal').on('click', function () {
    const quantidadeBaixar = parseFloat($('#txtQuantidadeBaixarModal').val().replaceAll(',', '.')) || 0
    const quantidadeEstornar = parseFloat($('#txtQuantidadeEstornarModal').val().replaceAll(',', '.')) || 0
    atualizarQuantidadesRegistro({ quantidadeBaixar, quantidadeEstornar })
  })

  function atualizarQuantidadesRegistro({ quantidadeBaixar, quantidadeEstornar }) {
    try {
      const datatable = $('#tabelaItens').DataTable()
      const [indiceLinhaSelecionada] = datatable.rows({ selected: true }).indexes().toArray()

      if (indiceLinhaSelecionada === undefined && indiceLinhaSelecionada === null) {
        return
      }

      const linhaSelecionada = datatable.row(indiceLinhaSelecionada)
      const dadosAtuais = linhaSelecionada.data()
      const saldoAtual = dadosAtuais.saldo - dadosAtuais.quantidadeBaixar;

      if (saldoAtual < quantidadeBaixar) {
        msgAlerta('Quantidade a baixar não pode ser superior à quantidade da ordem de compra, impossível continuar.');
        return;
      }

      if (dadosAtuais.quantidadeBaixada < quantidadeEstornar) {
        msgAlerta('Quantidade a estornar não pode ser superior à quantidade baixada, impossível continuar.');
        return;
      }

      const dadosAtualizados = { ...dadosAtuais, quantidadeBaixar, quantidadeEstornar }
      linhaSelecionada.data(dadosAtualizados).draw(false)

      $('#modalManutencao').modal('hide')
      atualizaTotais();
    } catch (error) {
      console.error(error)
      msgErro('Ocorreu um erro ao atualizar o registro.')
    }
  }

  $('#modalManutencao').on('hide.bs.modal', function () {
    $('#tabelaItens').DataTable().rows().deselect()
  })

  $('#txtBarra').on('blur', function () {
    const quantidade = Number($('#txtQuantidade').val()) || 1
    const barra = this.value
    if (!barra) {
      return
    }

    $.LoadingOverlay('show')
    lerBarra(barra).then(({ sucesso, mensagem, resultado }) => {
      if (!sucesso) {
        msgErro(mensagem)
        return
      }

      const data = $('#tabelaItens').DataTable().data().toArray()
      const index = data.findIndex((item) => item.codigo === resultado.codigo && item.cor === resultado.cor && item.tamanho === resultado.tamanho)
      if (index === -1) {
        msgErro('Item bipado não encontrado nos itens consultados, favor verificar.')
        return
      }
      const item = data[index]

      if (item.saldo < (item.quantidadeBaixar + quantidade)) {
        msgErro('Quantidade a baixar não pode ser superior ao saldo, impossível continuar.')
        return
      }

      item.quantidadeBaixar += quantidade;
      item.sel = true;
      data[index] = item

      const novoArray = [item, ...data.slice(0, index), ...data.slice(index + 1)];

      criarTabelaItens({ data: novoArray })
    }).catch((error) => {
      console.error(error)
      msgErro('Ocorreu um erro ao ler a barra.')
    }).finally(() => {
      $('#txtBarra').val('')
      $('#txtBarra').focus()
      $.LoadingOverlay('hide')
    })
  })



  async function lerBarra(barra) {
    try {
      const response = await requisicao('GET', `/sisplan/baixa_ordem_compra/v1/barra?`, `BARRA=${encodeURIComponent(barra)}`, '', 3600000)
      const json = await response.json()

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

        return {
          sucesso: true,
          resultado,
        }
      }
    } catch (error) {

    } finally {

    }
  }
})