class Tableless::TabelaAlteracaoEmpenho
	include ActiveModel::Model

	attr_accessor :orcamento
  attr_accessor :lista

  def iniciar_lista(saldo)
    @lista = []
    @lista_de_movimentacoes = []
    self.adicionar(:saldo_inicial, saldo)
  end

  def adicionar(tipo, saldo)
    @lista << {tipo: tipo, saldo: saldo, valor_original: saldo, reducoes: 0, anulacoes: 0, empenhado: 0}
  end

  def adicionar_empenho(empenho_id, tipo_anterior, valor)
    @lista << {tipo: :empenho, empenho_id: empenho_id, valor_original: valor, tipo_anterior: tipo_anterior, anulacoes: 0, saldo: valor}
  end

  def remover_saldo_dotacao_origem(valor_a_retirar)
    nova_lista = []
    @lista.reverse_each do |item|
      unless item[:tipo].eql?(:empenho)
        if valor_a_retirar >= item[:saldo]
          valor_a_retirar -= item[:saldo]
          item[:reducoes] += item[:saldo]
          item[:saldo] = 0
        else
          item[:saldo] -= valor_a_retirar
          item[:reducoes] += valor_a_retirar
          valor_a_retirar = 0
        end
      end

      nova_lista << item
    end

    @lista = nova_lista.reverse
  end

  def remover_saldo_anulacao(valor_a_retirar, id_do_empenho)
    nova_lista = []
    valor_a_retirar_do_empenho = valor_a_retirar

    tipo = @lista.select{ |i| i[:empenho_id] == id_do_empenho }.first[:tipo_anterior] rescue nil

    if tipo.present?
      @lista.each do |item|

        if item[:tipo].eql?(:empenho) and item[:empenho_id] == id_do_empenho
          item[:anulacoes] += valor_a_retirar_do_empenho
          item[:saldo] = item[:valor_original] - item[:anulacoes]
        end

        nova_lista << item
      end

      @lista = nova_lista
    end

  end


  def gerar_tabela(orcamento)
    #@lista.each do |item|
      #puts "#{item[:tipo].to_s.rjust(20, ' ')} | #{item[:valor_original].to_f.contabil.to_s.rjust(12, ' ')} | #{item[:empenhado].to_f.contabil.to_s.rjust(12, ' ')} | #{item[:reducoes].to_f.contabil.to_s.rjust(12, ' ')} | #{item[:anulacoes].to_f.contabil.to_s.rjust(12, ' ')} | #{item[:saldo].to_f.contabil.to_s.rjust(12, ' ')}"
    #end
    
    lista_empenhos = []
    lista_dotacoes = []

    @lista.each do |item|
      lista_dotacoes << item unless item[:tipo] == :empenho
    end

    @lista.each do |item|
      if item[:tipo] == :empenho
        while item[:saldo] > 0
          index = 0
          #byebug if item[:empenho_id] == 45471
          lista_dotacoes.each do |dotacao|
            if item[:saldo] >= dotacao[:saldo]
              lista_empenhos << {empenho_id: item[:empenho_id], valor: dotacao[:saldo], tipo: dotacao[:tipo]}
              item[:saldo] -= dotacao[:saldo]
              dotacao[:saldo] = 0
              lista_dotacoes.delete_at(index)
              #byebug if item[:empenho_id] == 45471
            else
              lista_empenhos << {empenho_id: item[:empenho_id], valor: item[:saldo], tipo: dotacao[:tipo]}
              dotacao[:saldo] -= item[:saldo]
              item[:saldo] = 0
              #byebug if item[:empenho_id] == 45471
            end

            break if item[:saldo] == 0

            index += 1
          end

          #byebug if item[:empenho_id] == 45471
        end
      #else
        #lista_dotacoes << item
      end

    end

    #puts "    "
    #puts "    "

    tabela = []
    lista_empenhos.select{ |i| i if i[:valor] > 0}.compact.group_by { |i| i[:empenho_id]}.each do |grupo, movimentos|
      movimentos = calcular_dados_do_empenho(grupo, movimentos)
      movimentos.each do |movimento|
        tabela << movimento
      end
    end


    tabela_final = []
    tabela.group_by { |i| [i[:empenho_id], i[:liquidacao_id], i[:pagamento_id], i[:tipo]]}.each do |grupo, movimentos|
      tabela_final << {empenho_id: grupo[0], liquidacao_id: grupo[1], pagamento_id: grupo[2], tipo: grupo[3], valor: movimentos.inject(0) { |t, i| t += i[:valor]}}
    end

    tabela_final.each do |item|
      EmpenhoParaFechamentoPcasp.create(empenho_id: item[:empenho_id], liquidacao_id: item[:liquidacao_id], pagamento_id: item[:pagamento_id], valor: item[:valor], tipo: item[:tipo], orcamento_id: orcamento.id)
      #puts "#{item[:empenho_id].to_s.rjust(6, ' ')} | #{item[:valor].to_f.contabil.to_s.rjust(13, ' ')} | #{item[:tipo].to_s.rjust(20, ' ')}"
    end

  end

  def calcular_dados_do_empenho(empenho_id, movimentos)
    empenho = Contabilidade::Empenho.find(empenho_id)
    liquidacoes = empenho.liquidacoes.confirmadas_ate_autorizadas.do_orcamento.where("estornada is false or estornada is null").map { |i| {id: i.id, empenho_id: i.empenho_id, valor: i.valor, numero: i.numero, status: i.status, estornada: i.estornada} }

    movimentos_de_liquidacao = []

    movimentos.each do |movimento|
      saldo_movimento = movimento[:valor]

      liquidacoes.sort_by{ |i| i[:numero] }.each do |liquidacao|
        if liquidacao[:valor] >= saldo_movimento
          movimentos_de_liquidacao << {empenho_id: empenho_id, liquidacao_id: liquidacao[:id], tipo: movimento[:tipo], valor: saldo_movimento}
          liquidacao[:valor] -= saldo_movimento
          saldo_movimento = 0
        else
          movimentos_de_liquidacao << {empenho_id: empenho_id, liquidacao_id: liquidacao[:id], tipo: movimento[:tipo], valor: liquidacao[:valor]}
          saldo_movimento -= liquidacao[:valor]
          liquidacao[:valor] = 0
        end

        liquidacoes.delete_if { |i| i[:valor] == 0 }
        break if saldo_movimento == 0
      end

    end

    movimentos_de_liquidacao = self.calcular_dados_da_liquidacao(movimentos_de_liquidacao)

    return movimentos + movimentos_de_liquidacao

  end

  def calcular_dados_da_liquidacao(movimentos)
    movimentos_de_pagamento = []
    movimentos.each do |movimento|
      #byebug if movimento[:empenho_id] == 47121
      liquidacao = Contabilidade::Liquidacao.find(movimento[:liquidacao_id])

      if liquidacao.estornada?
        movimento[:valor] = 0
      end

      pagamentos = liquidacao.pagamentos.confirmados_ou_superior.do_orcamento.map { |i| {id: i.id, empenho_id: i.liquidacao.empenho_id, liquidacao_id: i.liquidacao_id, valor: i.valor, data: i.data, status: i.status, estornado: i.estornado} }

      pagamentos.each do |pagamento|
        movimentos_de_pagamento.each do |movimento_de_pagamento|
          if pagamento[:id] == movimento_de_pagamento[:pagamento_id]
            pagamento[:valor] -= movimento_de_pagamento[:valor]
            pagamentos.delete_if { |i| i[:valor] == 0 }
          end
        end
      end

      unless movimento[:valor] == 0
        saldo_movimento = movimento[:valor]

        pagamentos.sort_by{ |i| i[:data]}.each do |pagamento|
            if pagamento[:valor] >= saldo_movimento
              movimentos_de_pagamento << {empenho_id: pagamento[:empenho_id], liquidacao_id: pagamento[:liquidacao_id], pagamento_id: pagamento[:id], tipo: movimento[:tipo], valor: saldo_movimento}
              pagamento[:valor] -= saldo_movimento
              saldo_movimento = 0
              #byebug if pagamento[:id] == 19708
            else
              movimentos_de_pagamento << {empenho_id: pagamento[:empenho_id], liquidacao_id: pagamento[:liquidacao_id], pagamento_id: pagamento[:id], tipo: movimento[:tipo], valor: pagamento[:valor]}
              saldo_movimento -= pagamento[:valor]
              pagamento[:valor] = 0
              #byebug if pagamento[:id] == 19708
            end

            #byebug if pagamento[:id] == 19708
            pagamentos.delete_if { |i| i[:valor] == 0 }
            break if saldo_movimento == 0
        end
      end

      #byebug if movimento[:empenho_id] == 47121
    end

    return movimentos + movimentos_de_pagamento
  end

end
