class Licitacao::OrcamentoDaDespesaDoContrato < ApplicationRecord
	has_paper_trail

	attr_accessor :elemento_de_despesa_por_subacao_id, :subacao_id

	belongs_to :contrato, class_name: 'Licitacao::Contrato', required: true, inverse_of: 'orcamentos_da_despesa_do_contrato'
	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_contrato, class_name: "Licitacao::ItemDoOrcamentoDaDespesaDoContrato", 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, :contrato_id, :sub_elemento_de_despesa_id
	validates_uniqueness_of :orcamento_da_despesa_id, scope: [:contrato_id, :sub_elemento_de_despesa_id]

	validate :valida_elemento_de_despesa_para_contrato_de_obra, if: Proc.new { sub_elemento_de_despesa.present? && contrato.present? && contrato.contrato_de_obras? }

	validates :itens_do_orcamento_da_despesa_do_contrato, uniq_nested_attributes: { atributo: :item_do_contrato_id, mensagem: "item deve ser único dentro de uma dotação" }

	accepts_nested_attributes_for :itens_do_orcamento_da_despesa_do_contrato, reject_if: :all_blank, allow_destroy: true

	after_save :atualiza_valor, unless: Proc.new { itens_do_orcamento_da_despesa_do_contrato.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.try(:modulo).try(: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.try(: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_contrato item_do_contrato
		item_do_contrato.quantidade_total.to_f - contrato.itens_dos_orcamentos_da_despesa_do_contrato.where(item_do_contrato: item_do_contrato).sum(:quantidade).to_f
	end

	def valida_elemento_de_despesa_para_contrato_de_obra
		if contrato.contrato_de_obras? && !sub_elemento_de_despesa.elemento_de_despesa.obra? #Elemento de despesa 51: Obras e Instalações
			errors.add(:elemento_de_despesa_por_subacao_id, "Para Contratos de Obra, o elemento de despesa deve ser o 51")
		end
	end

	private

	def atualiza_valor
		novo_valor =
			itens_do_orcamento_da_despesa_do_contrato.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
