class Patrimonio::MovimentacaoFinanceiraDoBem < ApplicationRecord

  include SimConcern

  has_paper_trail

  belongs_to :bem_patrimonial
  belongs_to :origem, polymorphic: true

  has_many :linhas, as: :modulo, class_name: "Tcm::Linha", dependent: :destroy

  validates_presence_of :bem_patrimonial_id, :data_da_movimentacao, :valor_inicial, :valor_da_operacao, :valor_final

  after_commit :define_situacao_para_o_sim, if: Proc.new { origem_type.present? && !self.destroyed?}
  after_commit :define_situacao_sim, if: Proc.new { origem_type.present? && !self.destroyed?}

  enum situacao: {
    reavaliacao_aumentativa: 1,
    reavaliacao_diminutiva: 2,
    molhorias_adicionais: 3,
    desincorporacao_alienacao: 4,
    desincorporacao_inservivel: 5,
    desincorporacao_outros: 6,
    ajuste_vpa: 7,
    ajuste_vpd: 8
	}

  enum situacao_sim: {
    depreciacao: 1,
    amortizacao: 2,
    extaustao: 3,
    reducao_valor_recuperavela: 4,
    reversao_da_reducao_valor_recuperavel: 5,
    baixa_depreciacao_acumulada: 6,
    baixa_amortizacao_acumulada: 7,
    baixa_exautao_acumulada: 8
  }

  def tipo_de_origem
    case origem_type
    when 'Patrimonio::AlteracaoDoValorDoBem'
      origem.tipo_de_alteracao_i18n
    when 'Patrimonio::BaixaDoBem'
      'Desreconhecimento do Bem'
    when 'Patrimonio::AvaliacaoDoBem'
      origem.tipo_de_avaliacao_i18n
    when 'Patrimonio::DepreciacaoDoBem'
      'Depreciação do Bem'
    else
      'Tombamento do Bem'
    end
  end

  def define_situacao_para_o_sim
    unless origem_type.nil?
      case origem_type
      when 'Patrimonio::AlteracaoDoValorDoBem'
        situacao =
          if origem.custo_subsequente?
            3
          elsif origem.reducao_de_valor?
            8
          elsif origem.baixa_depreciacao_acumulada?
            6
          elsif origem.ajuste_inicial?
            valor_alterado.to_d.positive? ? 1 : 2
          end
      when 'Patrimonio::BaixaDoBem'
        situacao =
          if origem.venda?
            4
          elsif origem.inservivel?
            5
          else
            6
          end
      when 'Patrimonio::AvaliacaoDoBem'
        situacao = valor_da_operacao.to_d.positive? ? 1 : 2
      when 'Patrimonio::DepreciacaoDoBem'
        situacao = 8
      end
      self.update_column(:situacao, situacao)
    end
  end

  def define_situacao_sim
    unless origem_type.nil?
      case origem_type
      when 'Patrimonio::AlteracaoDoValorDoBem'
        situacao_sim =
          if origem.baixa_depreciacao_acumulada?
            6
          elsif origem.ajuste_inicial?
            valor_alterado.to_d.positive? ? 5 : 4
          end
      when 'Patrimonio::AvaliacaoDoBem'
        situacao_sim = valor_da_operacao.to_d.positive? ? 5 : 4
      when 'Patrimonio::DepreciacaoDoBem'
        situacao_sim = 1
      end
      self.update_column(:situacao_sim, situacao_sim) unless self.destroyed?
    end
  end

  def unidade_orcamentaria(gestora_id, exercicio)
    unid = Loa::UnidadeOrcamentaria.joins(:unidade_gestora).joins(orgao: :orcamento).where("loa_unidades_gestoras.id = #{gestora_id} AND orcamentos.exercicio = #{exercicio}").order(:codigo).first

    ultima_unid_disponivel = Loa::UnidadeOrcamentaria.joins(:unidade_gestora).joins(orgao: :orcamento).where("loa_unidades_gestoras.id = #{gestora_id}").order('orcamentos.exercicio DESC').first

    unid = unid.nil? ? Loa::UnidadeOrcamentariaVinculada.find_by_unidade_orcamentaria_vinculada_id(ultima_unid_disponivel.id).try(:unidade_orcamentaria) : unid

    unid = unid.nil? ? ultima_unid_disponivel : unid

    return unid
  end

  def vida_util_to_sim(data_referencia)
    ultima_avaliacao = self.bem_patrimonial.avaliacoes_dos_bens.where("data_da_avaliacao >= '#{data_referencia.sim_data}'").order(:data_da_avaliacao).last
    vida_util = ultima_avaliacao.present? ? ultima_avaliacao.vida_util.to_i : self.bem_patrimonial.dados_extras_do_bem.vida_util.to_i

    return vida_util
  end

  def to_sim_ajuste_reavaliacao_patrimonial(data_referencia)
    # agente = self.bem_patrimonial.localizacao_na_data(self.data_da_movimentacao).agente_publico_municipal
    uo = unidade_orcamentaria(bem_patrimonial.unidade_gestora_id, self.data_da_movimentacao.year)
    agente = uo.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)
    depreciavel_atualizado = self.valor_final.to_d - self.bem_patrimonial.dados_extras_do_bem.valor_residual.to_d

    begin
      texto = ""
      texto << "982".sim_preenche(3) + "," #1
      texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
      texto << self.bem_patrimonial.tombamento_to_sim(uo.id).sim_limite(20) + "," #3
      texto << self.data_da_movimentacao.sim_data + "," #4
      texto << data_referencia.sim_data.first(6) + "," #5
      texto << self.data_da_movimentacao.sim_data.first(4) + '00' + "," #6
      texto << uo.orgao.codigo.sim_preenche(2) + "," #7
      texto << uo.codigo.codigo_uo_to_sim + "," #8
      texto << (agente.cpf.sim_limite(11) ) + "," #9
      texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s.sim_preenche(1)) + "," #10
      texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s.sim_preenche(1)) + "," #11
      texto << (agente.numero_da_portaria.to_s.sim_limite(10)) + "," #12
      # texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).present? ? agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s : "N").sim_preenche(1) + "," #10
      # texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).present? ? agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s : "E").sim_preenche(1) + "," #11
      # texto << (agente.numero_da_portaria.to_s == '' ? 'PORTARIA' : agente.numero_da_portaria.to_s).sim_limite(10) + "," #12
      texto << self.read_attribute_before_type_cast(:situacao).to_s + "," #13
      texto << self.valor_da_operacao.to_d.abs.to_s.sim_valor + "," #14
      texto << (self.origem.try(:observacao).to_s == '' ? "DEPRECIAÇÃO DO PERÍODO" : self.origem.try(:observacao).to_s).sim_descricao.sim_limite(255) + ","#15
      texto << self.bem_patrimonial.dados_extras_do_bem.valor_residual.to_d.to_s.sim_valor + "," #16
      texto << depreciavel_atualizado.to_s.sim_valor + "," #17
      texto << vida_util_to_sim(self.data_da_movimentacao).to_s.sim_preenche(2).delete("'") #18

      return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, self.bem_patrimonial.numero_do_tombamento , atributo_falho, coluna)
			else
				raise e
			end
		end
  end


  def to_sim_ajuste_reavaliacao_patrimonial_temporaria(data_referencia, total)
    # agente = self.bem_patrimonial.localizacao_na_data(self.data_da_movimentacao).agente_publico_municipal
    uo = unidade_orcamentaria(bem_patrimonial.unidade_gestora_id, self.data_da_movimentacao.year)
    agente = uo.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)
    depreciavel_atualizado = self.valor_final.to_d - self.bem_patrimonial.dados_extras_do_bem.valor_residual.to_d

    begin
      texto = ""
      texto << "982".sim_preenche(3) + "," #1
      texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
      texto << self.bem_patrimonial.tombamento_to_sim(uo.id).sim_limite(20) + "," #3
      texto << self.data_da_movimentacao.sim_data + "," #4
      texto << data_referencia.sim_data.first(6) + "," #5
      texto << self.data_da_movimentacao.sim_data.first(4) + '00' + "," #6
      texto << uo.orgao.codigo.sim_preenche(2) + "," #7
      texto << uo.codigo.codigo_uo_to_sim + "," #8
      texto << (agente.cpf.sim_limite(11)) + "," #9
      texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s.sim_preenche(1)) + "," #11
      texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s.sim_preenche(1)) + "," #12
      texto << (agente.numero_da_portaria.to_s.sim_limite(10)) + "," #13
      # texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).present? ? agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s : "N").sim_preenche(1) + "," #10
      # texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).present? ? agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s : "E").sim_preenche(1) + "," #11
      # texto << (agente.numero_da_portaria.to_s == '' ? 'PORTARIA' : agente.numero_da_portaria.to_s).sim_limite(10) + "," #12
      texto << self.read_attribute_before_type_cast(:situacao).to_s + "," #13
      texto << total.to_s.sim_valor + "," #14
      texto << (self.origem.try(:observacao).to_s == '' ? "DEPRECIAÇÃO DO PERÍODO" : self.origem.try(:observacao).to_s).sim_descricao.sim_limite(255) #15
      texto << self.bem_patrimonial.dados_extras_do_bem.valor_residual.to_d.to_s.sim_valor + "," #16
      texto << depreciavel_atualizado.to_s.sim_valor + "," #17
      texto << vida_util_to_sim(self.data_da_movimentacao).to_s.sim_preenche(2).delete("'") #18

      return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, self.bem_patrimonial.numero_do_tombamento , atributo_falho, coluna)
			else
				raise e
			end
		end
  end

  def to_sim_contas_redutoras_dos_bens(data_referencia)
    # agente = self.bem_patrimonial.localizacao_na_data(self.data_da_movimentacao).agente_publico_municipal
    uo = unidade_orcamentaria(bem_patrimonial.unidade_gestora_id, self.data_da_movimentacao.year)
    agente = uo.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)

    begin
      texto = ""
      texto << "984".sim_preenche(3) + "," #1
      texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
      texto << self.bem_patrimonial.tombamento_to_sim(uo.id).sim_limite(20) + "," #3
      texto << self.data_da_movimentacao.sim_data + "," #4
      texto << self.read_attribute_before_type_cast(:situacao_sim).to_s + "," #5
      texto << data_referencia.sim_data.first(6) + "," #6
      texto << self.data_da_movimentacao.sim_data.first(4) + '00' + "," #7
      texto << uo.orgao.codigo.sim_preenche(2) + "," #8
      texto << uo.codigo.codigo_uo_to_sim + "," #9
      texto << (agente.cpf.sim_limite(11)) + "," #10
      texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s.sim_preenche(1)) + "," #11
      texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s.sim_preenche(1)) + "," #12
      texto << (agente.numero_da_portaria.to_s.sim_limite(10)) + "," #13
      # texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).present? ? agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s : "N").sim_preenche(1) + "," #11
      # texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).present? ? agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s : "E").sim_preenche(1) + "," #12
      # texto << (agente.numero_da_portaria.to_s == '' ? 'PORTARIA' : agente.numero_da_portaria.to_s).sim_limite(10) + "," #13
      texto << self.valor_da_operacao.to_d.abs.to_s.sim_valor + "," #14
      texto << (self.origem.try(:observacao).to_s == '' ? "DEPRECIAÇÃO DO PERÍODO" : self.origem.try(:observacao).to_s).sim_descricao.sim_limite(255) #15

      return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
        raise e.mensagem_traduzida(self, self.bem_patrimonial.numero_do_tombamento , atributo_falho, coluna)
			else
				raise e
			end
		end
  end

  def to_sim_contas_redutoras_dos_bens_temporario(data_referencia, total)
    # agente = self.bem_patrimonial.localizacao_na_data(self.data_da_movimentacao).agente_publico_municipal
    uo = unidade_orcamentaria(bem_patrimonial.unidade_gestora_id, self.data_da_movimentacao.year)
    agente = uo.unidade_gestora.gestor_no_periodo(data_referencia.end_of_month)

    begin
      texto = ""
      texto << "984".sim_preenche(3) + "," #1
      texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
      texto << self.bem_patrimonial.tombamento_to_sim(uo.id).sim_limite(20) + "," #3
      texto << self.data_da_movimentacao.sim_data + "," #4
      texto << self.read_attribute_before_type_cast(:situacao_sim).to_s + "," #5
      texto << data_referencia.sim_data.first(6) + "," #6
      texto << self.data_da_movimentacao.sim_data.first(4) + '00' + "," #7
      texto << uo.orgao.codigo.sim_preenche(2) + "," #8
      texto << uo.codigo.codigo_uo_to_sim + "," #9
      texto << (agente.cpf.sim_limite(11)) + "," #10
      texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s.sim_preenche(1)) + "," #11
      texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s.sim_preenche(1)) + "," #12
      texto << (agente.numero_da_portaria.to_s.sim_limite(10)) + "," #13
      # texto << (agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).present? ? agente.read_attribute_before_type_cast(:ingresso_sistema_publico_municipal).to_s : "N").sim_preenche(1) + "," #11
      # texto << (agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).present? ? agente.read_attribute_before_type_cast(:tipo_relacao_servico_publico).to_s : "E").sim_preenche(1) + "," #12
      # texto << (agente.numero_da_portaria.to_s == '' ? 'PORTARIA' : agente.numero_da_portaria.to_s).sim_limite(10) + "," #13
      texto << total.to_s.sim_valor + "," #14
      texto << (self.origem.try(:observacao).to_s == '' ? "DEPRECIAÇÃO DO PERÍODO" : self.origem.try(:observacao).to_s).sim_descricao.sim_limite(255) #15

      return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
        raise e.mensagem_traduzida(self, self.bem_patrimonial.numero_do_tombamento , atributo_falho, coluna)
			else
				raise e
			end
		end
  end
end
