class Licitacao::OrcamentoDaDespesaDoAditivo < ApplicationRecord
	has_paper_trail

	attr_accessor :elemento_de_despesa_por_subacao_id, :subacao_id

	belongs_to :aditivo, class_name: 'Licitacao::Aditivo', required: true, inverse_of: 'orcamentos_da_despesa_do_aditivo'
	belongs_to :orcamento_da_despesa, class_name: "Loa::OrcamentoDaDespesa", required: true
	belongs_to :sub_elemento_de_despesa, class_name: "Contabilidade::SubElementoDeDespesa"

	has_many :itens_do_orcamento_da_despesa_do_aditivo, class_name: "Licitacao::ItemDoOrcamentoDaDespesaDoAditivo", dependent: :destroy

	delegate :elemento_de_despesa_por_subacao, to: :orcamento_da_despesa, allow_nil: true
	delegate :subacao, to: :elemento_de_despesa_por_subacao, allow_nil: true

	validates_presence_of :orcamento_da_despesa_id, :aditivo_id, :sub_elemento_de_despesa_id
	validates_uniqueness_of :orcamento_da_despesa_id, scope: [:aditivo_id, :sub_elemento_de_despesa_id]

	validate :valida_valor_total_do_aditivo, if: Proc.new { self.aditivo.nova_unidade_orcamentaria? }

	accepts_nested_attributes_for :itens_do_orcamento_da_despesa_do_aditivo, reject_if: :all_blank, allow_destroy: true

	after_save :atualiza_valor, unless: Proc.new { itens_do_orcamento_da_despesa_do_aditivo.empty? }

	def classificacao
		"#{orcamento_da_despesa.orgao.try(:codigo)} #{orcamento_da_despesa.unidade_orcamentaria.try(:codigo_formatado)} #{orcamento_da_despesa.subacao.try(:funcao).try(:codigo)} #{orcamento_da_despesa.subacao.try(:subfuncao).try(:codigo)} #{orcamento_da_despesa.subacao.try(:acao).try(:programa_de_governo).try(:codigo)} #{orcamento_da_despesa.subacao.try(:acao).try(:codigo_completo)} #{orcamento_da_despesa.subacao.try(:codigo) if orcamento_da_despesa.fonte_de_recursos.modulo.trabalha_com_subacao?}"
	end

	def classificacao_completa
		"#{classificacao} #{sub_elemento_de_despesa.try(:codigo_formatado)}"
	end

	def classificacao_completa_com_subelemento
		"#{orcamento_da_despesa.classificacao_parcial}
		#{subacao.try(:acao).try(:codigo_completo)}
		#{subacao.try(:codigo) if orcamento_da_despesa.fonte_de_recursos.modulo.trabalha_com_subacao?}
		#{sub_elemento_de_despesa.codigo_formatado}
		#{orcamento_da_despesa.fonte_de_recursos.codigo_completo}"
	end

	def variante_da_classificacao_completa_com_subelemento
		"#{orcamento_da_despesa.classificacao_parcial}
		#{subacao.try(:acao).try(:codigo_completo)}
		#{subacao.try(:codigo) if orcamento_da_despesa.fonte_de_recursos.modulo.trabalha_com_subacao?}
		#{sub_elemento_de_despesa.variante_do_codigo_formatado}
		#{orcamento_da_despesa.fonte_de_recursos.codigo_completo}"
	end

	def saldo_a_vincular_por_item_do_aditivo item_do_aditivo
		item_do_aditivo.quantidade.to_f - aditivo.itens_dos_orcamentos_da_despesa_do_aditivo.where(item_do_aditivo: item_do_aditivo).sum(:quantidade).to_f
	end

	def valida_valor_total_do_aditivo
		despesas = aditivo.orcamentos_da_despesa_do_aditivo.where.not(id: id)
		valor_disponivel_para_dotacoes = aditivo.contrato.valor_a_empenhar_no_periodo_vigente.to_d - despesas.sum(:valor)

		if valor > valor_disponivel_para_dotacoes
			errors.add(:valor, "O valor total do aditivo não pode ser maior que o saldo da dotação.")
		end
	end

	private

	def atualiza_valor
		novo_valor =
			itens_do_orcamento_da_despesa_do_aditivo.inject(0) do |total, item_do_orcamento|
				total + item_do_orcamento.total_por_item.to_f
			end

		self.update_column(:valor, novo_valor) if valor.to_f != novo_valor.to_f
	end
end
