class Ppa::Programa < ApplicationRecord
	include CalculaDespesasDoPrograma
	include CalculaParaRelatoriosAsDespesasDoPrograma
	include IncrementadorDeCodigoConcern

	has_paper_trail

	belongs_to :ppa
	belongs_to :tipo_de_programa
	belongs_to :orgao
	belongs_to :eixo

	has_many :projecoes_de_despesa, as: :orcador, dependent: :restrict_with_exception
	has_many :objetivos, dependent: :restrict_with_exception
	has_many :iniciativas, through: :objetivos
	has_many :metas, through: :objetivos
	has_many :indicadores, dependent: :destroy
	has_many :programas_de_governo, class_name: 'Loa::ProgramaDeGoverno', dependent: :restrict_with_exception

	validates_presence_of :nome, :codigo, :ppa_id, :tipo_de_programa_id, :orgao_id, :eixo_id

	validates_uniqueness_of :nome, scope: :ppa_id
	validates_uniqueness_of :codigo, scope: [:ppa_id, :tipo_de_programa_id]

	validates_numericality_of :codigo, less_than: 1000

	validates :ppa_id, immutable: true
	validate :deve_ter_o_mesmo_ppa_do_orgao_responsavel

	after_initialize :sugestao_de_codigo, if: :new_record?

	ransacker :codigo_completo do
		Arel.sql("tipo_de_programa_id::text || LPAD(codigo::text, 3, '0')")
	end

	def projecoes_de_despesa_resumidas
		projecoes_de_despesa_organizadas['resumo']
	end

	def codigo_e_nome
		"#{self.tipo_de_programa.codigo}#{self.codigo_com_zeros} - #{self.nome}"
	end

	def codigo_completo
		"#{self.tipo_de_programa.codigo}#{self.codigo_com_zeros}"
	end

	def codigo_com_zeros
		self.codigo.try(:digitos, 3)
	end

	private
		def deve_ter_o_mesmo_ppa_do_orgao_responsavel
			if self.orgao.try(:ppa_id) != ppa_id
				errors[:ppa_id] << "deve ser o mesmo PPA do Orgão Responsável"
			end
		end

		def sugestao_de_codigo
			gerar_sugestao_codigo( :codigo, 3, {ppa_id: ppa_id, tipo_de_programa_id: tipo_de_programa_id} ) if (ppa.present? && codigo.blank?)
		end

		def self.complemento_de_codigo tipo_de_programa_id, codigo_programa
			codigos_utilizados = ::Ppa::Programa.where(
				tipo_de_programa_id: tipo_de_programa_id, codigo: codigo_programa
			).order( :codigo ).pluck( :codigo ).map { |codigo|
				codigo.to_i
			}

			return codigo.try.digitos(3) if codigos_utilizados.empty?

			codigos_disponiveis = (1..codigos_utilizados.last.to_i + 1).to_a
			codigos_disponiveis.first
		end

		def atualiza_status_da_proposta_escolhida
			if self.proposta.present?
				proposta_escolhida = Ppa::Proposta.find( proposta_id )
				proposta_escolhida.update(status: 'lancada_no_ppa')
			end
		end

end
