class Ppa::Ppa < ApplicationRecord
	has_paper_trail

	include SeedFuncoesESubFuncoes
	include SeedEixos
	include SeedAreasTematicas
	include SeedPpaParticipativo
	include RelatoriosPpa
	include SeedNaturezasDaReceita
	include TradutorConcern
	include GeradorDeEventosContabeis


	enum status: {
		aberto: 0,
		em_votacao: 1,
		aprovado: 2
	}

	attr_default :status, :aberto

	attr_default :ppa_participativo_ativo, false

	attr_default :libera_votacao, false
	attr_default :libera_propostas, false
	attr_default :libera_problemas, true

	attr_default :ativar_somente_micro_regiao, false
	attr_default :ativar_somente_area_tematica, false
	attr_default :habilitar_termos_de_uso, true

	attr_default :quantidade_limite_de_propostas, 2
	attr_default :quantidade_de_caracteres_das_propostas, 140

	attr_default :chamada_para_envio_de_propostas, 'Envie sua proposta e seja parceiro no planejamento de governo.'
	attr_default :chamada_para_votacao_de_propostas, 'Ajude seu município a escolher as melhores propostas, participe da votação!'
	attr_default :pagina_principal, "<div style=""font-family:sans-serif; font-size:16.9898px; left:118.482px; text-align:justify; top:198.919px; transform:scaleX(0.952023)"">\r
<p>A Feliz Cidade que queremos para n&oacute;s e nossos filhos se constr&oacute;i por meio da participa&ccedil;&atilde;o popular. A realiza&ccedil;&atilde;o do Plano Plurianual Participativo (PPA-P) &eacute; mais um passo do nosso governo para consolidar o di&aacute;logo com a sociedade local. A democracia cidad&atilde;, com transpar&ecirc;ncia e participa&ccedil;&atilde;o ativa do povo, &eacute; mais que um compromisso, &eacute; um instrumento de planejamento da administra&ccedil;&atilde;o p&uacute;blica.<br />\r
As plen&aacute;rias do PPA Participativo que ocorrer&atilde;o em todos dos Distritos, bem como junto aos Conselhos de Sa&uacute;de, Assist&ecirc;ncia Social e Educa&ccedil;&atilde;o com vistas a amplia&ccedil;&atilde;o da participa&ccedil;&atilde;o popular e pleno atendimento a legisla&ccedil;&atilde;o vigente.</p>\r
\r
<p>A presen&ccedil;a dos mais variados segmentos sociais, contribuindo na constru&ccedil;&atilde;o e no monitoramento dos programas governamentais, dar&atilde;o prosseguimento a uma rela&ccedil;&atilde;o democr&aacute;tica entre o governo e a sociedade.</p>\r
\r
<p>Por isto, estamos convidando voc&ecirc; cidad&atilde;o para ser parceiro e correspons&aacute;vel pelo planejamento de governo que vai melhorar a qualidade de vida do povo da Felizcidade, terrade todos n&oacute;s.</p>\r
</div>"

	attr_default :termos_de_uso, "<p>O PLANO PLURIANUAL PPA &eacute; uma a&ccedil;&atilde;o destinada a realizar o planejamento do governo municipal para os pr&oacute;ximos 4 (quatro) anos, definindo os programas priorit&aacute;rios, seus valores e metas. Esses programas ser&atilde;o seguidos quando da elabora&ccedil;&atilde;o das pe&ccedil;as or&ccedil;ament&aacute;rias em que cada exerc&iacute;cio que compreendem o per&iacute;odo planejado.</p>
\r
<p>O PPA PARTICIPATIVO &eacute; uma ferramenta criada para dar ao cidad&atilde;o a possibilidade de participar da elabora&ccedil;&atilde;o do Planejamento Municipal, utilizando um canal no qual ele dever&aacute; registrar suas propostas ou apontar demandas para subsidiar a equipe de planejamento na elabora&ccedil;&atilde;o do PPA.</p>\r
\r
<p>&nbsp;</p>\r
\r
<p>Por este termo, com o qual eu concordo plenamente, comprometo-me a:</p>\r
\r
<p>1. Jamais utilizar o aplicativo para denegrir a imagem de pessoas, institui&ccedil;&otilde;es ou empresas inserindo nos formul&aacute;rios de participa&ccedil;&atilde;o textos com cr&iacute;ticas, den&uacute;ncias ou falsas not&iacute;cias;<br />\r
2. Jamais utilizar o aplicativo para promover candidatos, partidos pol&iacute;ticos, pol&iacute;ticos j&aacute; eleitos ou ideologias de qualquer natureza inserindo nos formul&aacute;rios de participa&ccedil;&atilde;o textos com elogios, promo&ccedil;&otilde;es ou propagandas;<br />\r
3. Jamais utilizar o aplicativo para qualquer outro fim que seja com o objetivo espec&iacute;fico de colaborar com sugest&otilde;es ou relatar problemas da comunidade para subsidiar a elabora&ccedil;&atilde;o do planejamento;<br />\r
4. Respeitar os limites estabelecidos nesse instrumento de participa&ccedil;&atilde;o como a quantidade de propostas com a qual posso contribuir e o tamanho do texto estabelecido para defini&ccedil;&atilde;o da minha proposta;<br />\r
5. Respeitar as decis&otilde;es da Equipe de Planejamento quanto &agrave; sele&ccedil;&atilde;o das propostas que compor&atilde;o o documento final do Plano Plurianual;<br />\r
6. Divulgar e difundir o uso dessa ferramenta para que mais cidad&atilde;os ou cidad&atilde;s da minha comunidade possa tamb&eacute;m participar;<br />\r
7. Votar nas propostas apresentadas por outros cidad&atilde;os ou cidad&atilde;s, consolidando assim, minha participa&ccedil;&atilde;o nesse processo de cidadania;<br />\r
8. O Plano Plurianual &eacute; uma pe&ccedil;a t&eacute;cnica, que tem metodologia pr&oacute;pria de elabora&ccedil;&atilde;o e apresenta&ccedil;&atilde;o, por isso, concordo que a minha proposta tenha o texto modificado para corre&ccedil;&atilde;o de eventuais erros ortogr&aacute;ficos ou de concord&acirc;ncia e tamb&eacute;m que possa ser combinada com texto de outra proposta semelhante desde que isso n&atilde;o descaracterize a ideia central por mim elaborada;</p>"

	has_settings do |s|
		s.key :configuracoes, defaults: { detalhar_despesas_nas_iniciativas: false }
	end

	has_attached_file :capa_de_apresentacao_ppa_participativo, styles: { medium: "300x300>", thumb: "100x100>" },
	default_url: "/capa_padrao_ppa_participativo_:style.jpeg"

	validates_attachment_content_type :capa_de_apresentacao_ppa_participativo, content_type: /\Aimage\/.*\z/,
	message: 'arquivo selecionado não é uma imagem'

	has_one :projecao_de_receita, class_name: 'Projecao::ProjecaoDeReceita', dependent: :destroy, as: :planejamento

	has_many :funcoes, dependent: :destroy
	has_many :orgaos, dependent: :restrict_with_exception
	has_many :unidades_orcamentarias, through: :orgaos
	has_many :convenios, dependent: :restrict_with_exception
	has_many :valores_do_convenio, through: :convenios
	has_many :eixos, dependent: :destroy
	has_many :regioes, dependent: :restrict_with_exception
	has_many :micro_regioes, through: :regioes
	has_many :tecnicos,class_name: 'Base::Tecnico', as: :modulo, dependent: :destroy
	has_many :programas, dependent: :restrict_with_exception
	has_many :areas_tematicas, dependent: :destroy
	has_many :paginas, class_name: 'Ppa::Pagina', dependent: :destroy
	has_many :propostas, class_name: 'Ppa::Proposta', dependent: :destroy
	has_many :impressao_das_receitas, class_name: 'Ppa::ImpressaoDaReceita', dependent: :destroy

	has_many :sub_areas_tematicas_dos_convenios, -> { distinct }, through: :convenios, source: :sub_area_tematica


	after_create :cria_funcoes_e_subfuncoes
	after_create :cria_eixos
	after_create :cria_areas_tematicas
	after_create :iniciar_projecao
	after_create :texto_ppa_participativo

	before_update :somente_um_ppa_participativo_com_periodo_de_propostas_e_votacao
	before_update :validar_termos_de_uso_vazio

	validates_numericality_of :quantidade_limite_de_propostas, greater_than_or_equal_to: 0
	validates_numericality_of :quantidade_de_caracteres_das_propostas, greater_than_or_equal_to: 0
	validates_numericality_of :exercicio_final, greater_than: :exercicio_inicial, message: "deve ser maior que o exercício inicial"

	validates_presence_of :exercicio_inicial, :exercicio_final, :prefeito, :vice_prefeito
	validates_presence_of :data_da_legislacao, if: Proc.new { legislacao.present? }
	validates_presence_of :legislacao, if: Proc.new { data_da_legislacao.present? }
	validates_presence_of :abertura_do_periodo_de_propostas, if: :fim_do_periodo_de_propostas
	validates_presence_of :fim_do_periodo_de_propostas, if: :abertura_do_periodo_de_propostas
	validates_presence_of :abertura_do_periodo_de_votacao, if: :fim_do_periodo_de_votacao
	validates_presence_of :fim_do_periodo_de_votacao, if: :abertura_do_periodo_de_votacao

	validates_numericality_of :exercicio_inicial
	validates_numericality_of :exercicio_final

	validates_length_of :exercicio_inicial, minimum: 4, maximum: 4
	validates_length_of :exercicio_final, minimum: 4, maximum: 4

	validate :diferenca_de_tempo_entre_exercicio_inicial_e_exercicio_final_deve_ser_4_anos
	#validate :votacao_proposta_impedido_de_salvar_ao_mesmo_tempo
	validate :valida_status_do_ppa
	validates :data_da_legislacao, date: { allow_blank: true }
	validates :fim_do_periodo_de_propostas, date: { allow_blank: true }
	validates :abertura_do_periodo_de_propostas, date: { allow_blank: true }
	validates :fim_do_periodo_de_votacao, date: { allow_blank: true }
	validates :abertura_do_periodo_de_votacao, date: { allow_blank: true }
	validates :abertura_do_periodo_de_propostas, data_maior_e_ou_menor_que: {menor_que: [:fim_do_periodo_de_propostas], mensagem: 'início do período de propostas deve ser menor que o término do período de propostas'}
	# validates :fim_do_periodo_de_propostas, data_maior_e_ou_menor_que: {menor_que: [:abertura_do_periodo_de_votacao], mensagem: 'término do período de propostas deve ser menor que o início do período de votação'}
	validates :abertura_do_periodo_de_votacao, data_maior_e_ou_menor_que: {menor_que: [:fim_do_periodo_de_votacao], mensagem: 'início do período de votação deve ser menor que o término do período de votação'}
	validates :exercicio_final, immutable: true
	validates :exercicio_inicial, immutable: true
	validates_uniqueness_of :ppa_participativo_ativo, if: :ppa_participativo_ativo

	validates_each :abertura_do_periodo_de_propostas, :abertura_do_periodo_de_votacao do |record, attr, value|
		if record.send(attr.to_s) != record.send(attr.to_s + '_was') && record.send(attr.to_s).present?
			record.errors.add(attr, "início do período deve ser maior ou igual a data de hoje (#{Date.current})") if value && value < Date.current
		end
	end

	has_attached_file :url_arquivo_de_contexto
	validates_attachment_content_type :url_arquivo_de_contexto, content_type: "application/pdf"
	validates_attachment_size :url_arquivo_de_contexto, in: 0..10.megabytes

	def mostra_os_temos_apos_edicao
		PpaParticipativo::Cidadao.update_all(aceitou_os_termos_de_uso: "false")
	end

	def movimentacoes_de_eventos_contabeis_do_ppa
		Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: "Ppa::Ppa").where(gerador_id: self.id)
	end

	def periodo
		exercicio_inicial..exercicio_final if (exercicio_inicial && exercicio_final)
	end

	def periodo_e_prefeito
		"#{exercicio_inicial.to_i} a #{exercicio_final.to_i} - #{self.prefeito}"
	end

	def intervalo
		return "#{exercicio_inicial} - #{exercicio_final}"
	end

	def estrutura_do_plano
		Ppa::Eixo.includes( programas: :objetivos ).where( ppa_id: self.id )
	end

	def configuracoes
		settings(:configuracoes)
	end

	def detalhar_despesas_nas_iniciativas!
		unless tem_iniciativas?
			configuracoes.detalhar_despesas_nas_iniciativas = true
			configuracoes.save
		end
		detalha_despesas_nas_iniciativas?
	end

	def capa_de_apresentacao_ppa_participativo_padrao?
		capa_de_apresentacao_ppa_participativo.original_filename == "capa_padrao_ppa_participativo.jpeg"
	end

	def detalha_despesas_nas_iniciativas?
		configuracoes.detalhar_despesas_nas_iniciativas
	end

	def tem_iniciativas?
		programas.joins( objetivos: :iniciativas ).count('ppa_iniciativas.id') > 0
	end

	def valor_total_da_despesa
		eixos.to_a.inject(0) {|total, eixo| total + eixo.valor_das_despesas.to_f}
	end

	def total_de_votos_das_propostas_do_ppa_participativo
		self.propostas.votaveis.inject(0) { |total, proposta| total + proposta.total_de_votos.to_i }
	end

	def total_geral_de_previsao_de_convenios
		self.valores_do_convenio.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }
	end

	def total_previsao_de_convenios_correntes
		self.valores_do_convenio.convenios_correntes.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }
	end

	def total_previsao_de_convenios_de_capital
		self.valores_do_convenio.convenios_de_capital.inject(0){|total, valor_do_convenio| total + valor_do_convenio.valor.to_f}
	end


	def total_geral_de_previsao_de_convenios_por_exercicio exercicio
		self.valores_do_convenio.select { |c| c.exercicio.eql?(exercicio) }.inject(0){|total, valor_do_convenio| total + valor_do_convenio.valor.to_f}
	end

	def total_previsao_de_convenios_correntes_por_exercicio exercicio
		self.valores_do_convenio.convenios_correntes.select { |c| c.exercicio.eql?(exercicio) }.inject(0){|total, valor_do_convenio| total + valor_do_convenio.valor.to_f}
	end

	def total_previsao_de_convenios_de_capital_por_exercicio exercicio
		self.valores_do_convenio.convenios_de_capital.select { |c| c.exercicio.eql?(exercicio) }.inject(0){|total, valor_do_convenio| total + valor_do_convenio.valor.to_f}
	end

	def possui_eixo_com_diretrizes?
		Ppa::Eixo.any? { |eixo| eixo.diretrizes.present? }
	end

	def titulo_para_relatorio_ppa
		titulo = self.aprovado? ? "Plano Plurianual " : "Projeto de Lei Plano Plurianual "
		titulo += exercicio_inicial.to_s + " / " + exercicio_final.to_s

		return titulo
	end

	def orgaos_que_participam_da_elaboracao_do_ppa
		Ppa::Orgao.where(participa_da_elaboracao_do_ppa: true)
	end

	def total_das_receitas_por_ppa
		total = 0

		(exercicio_inicial..exercicio_final).each do |exercicio|
			total += projecao_de_receita.total_das_receitas_por_exercicio_e_tipo exercicio
		end
		return total
	end

	def programas_invalidos
		ActiveRecord::Base.connection.execute( sql_programas_invalidos ).to_a
	end

	def valor_total_da_despesa_por_exercicio exercicio
		if detalha_despesas_nas_iniciativas?
			valor = ActiveRecord::Base.connection.execute( sql_despesa_por_iniciativa(exercicio) ).to_a.first['valor'] || 0
		else
			valor = ActiveRecord::Base.connection.execute( sql_despesa_por_programa(exercicio) ).to_a.first['valor'] || 0
		end

		return valor
	end

	def valor_total_da_despesa_por_exercicio_e_tipo_de_programa exercicio, tipo_de_programa_id
		if detalha_despesas_nas_iniciativas?
			valor = ActiveRecord::Base.connection.execute( sql_despesa_por_iniciativa(exercicio, tipo_de_programa_id) ).to_a.first['valor'] || 0
		else
			valor = ActiveRecord::Base.connection.execute( sql_despesa_por_programa(exercicio, tipo_de_programa_id) ).to_a.first['valor'] || 0
		end

		return valor
	end

	def tem_contexto?
		url_arquivo_de_contexto_updated_at.present?
	end

	def votacao_proposta_impedido_de_salvar_ao_mesmo_tempo
		if self.libera_votacao && self.libera_propostas
			errors.add(:libera_votacao, "Impossível liberar propostas e votação ao mesmo tempo.")
			errors.add(:libera_propostas, "Impossível liberar propostas e votação ao mesmo tempo.")
		end
	end

	def abrir_votacao
		if self.abertura_do_periodo_de_propostas.present? && Date.current < self.abertura_do_periodo_de_propostas
			message = 'Não foi possível liberar o período de votação'
			message << " pois é impossível liberar votação se data de abertura de propostas for maior que abertura de votação."
		else
			if abre_votacao(self)
				message = 'Período de votação liberado com sucesso.'
			else
				message = 'Não foi possível liberar o período de votação'
				message << " pois o período estabelecido anteriormente já passou" if Date.current > (self.fim_do_periodo_de_votacao || Date.current)
				message << ". Por favor, configure um novo período na tela de configurações do PPA Participativo" if self.errors[:abertura_do_periodo_de_votacao].any?
				message + '.'
			end
		end
	end

	def abre_votacao(ppa)
		Ppa::Ppa.transaction do

			# fechar_propostas if ppa.libera_propostas

			novos_atributos = {libera_votacao: true}
			novos_atributos.merge!({abertura_do_periodo_de_votacao: Date.current}) if self.abertura_do_periodo_de_votacao
			if ppa.update(novos_atributos)
				return true
			else
				raise ActiveRecord::Rollback
			end
		end
	end

	def fechar_votacao
		novos_atributos = { libera_votacao: false }
		if self.abertura_do_periodo_de_votacao == Date.current
			self.abertura_do_periodo_de_votacao = nil
			self.fim_do_periodo_de_votacao = nil
		elsif self.fim_do_periodo_de_votacao
			novos_atributos.merge!({ fim_do_periodo_de_votacao: Date.current - 1 })
		end

		if self.update(novos_atributos)
			message = 'Período de votação fechado com sucesso.'
		else
			message = 'Não foi possível fechar o período de votação'
			message << ". Altere o período  manualmente" if self.errors[:abertura_do_periodo_de_votacao].any?
			message + "."
		end
	end

	def abrir_propostas
		if Date.current < (self.abertura_do_periodo_de_votacao || Date.current)
			message = 'Não foi possível liberar o período de propostas'
			message << " pois é impossível liberar proposta se data de abertura de votação for maior que abertura de proposta."
		else
			if abre_proposta(self)
				message = 'Período de envio de propostas aberto com sucesso.'
			else
				message = 'Não foi possível liberar o período de envio de propostas'
				message << " pois o período estabelecido anteriormente já passou" if self.fim_do_periodo_de_propostas.present? && Date.current > self.fim_do_periodo_de_propostas
				message << ". Por favor, configure um novo período na tela de configurações do PPA Participativo" if self.errors[:abertura_do_periodo_de_propostas].any?
				message + "."
			end
		end
	end

	def abre_proposta(ppa)
		Ppa::Ppa.transaction do
			# fechar_votacao if ppa.libera_votacao
			novos_atributos = {libera_propostas: true}
			novos_atributos.merge!({abertura_do_periodo_de_propostas: Date.current}) if self.abertura_do_periodo_de_propostas
			if self.update(novos_atributos)
				return true
			else
				raise ActiveRecord::Rollback
			end
		end
	end

	# TODO: refatorar
	def fechar_propostas
		novos_atributos = {libera_propostas: false}
		if self.abertura_do_periodo_de_propostas == Date.current
			self.abertura_do_periodo_de_propostas = nil
			self.fim_do_periodo_de_propostas = nil
		elsif self.fim_do_periodo_de_propostas
			novos_atributos.merge!({ fim_do_periodo_de_propostas: Date.current - 1 })
		end
		if self.update(novos_atributos)
			message = 'Período de propostas fechado com sucesso.'
		else
			message = "Não foi possível fechar envio de propostas"
			message << ". Altere o período  manualmente" if self.errors[:abertura_do_periodo_de_propostas].any?
			message + '.'
		end
	end

	def utiliza_novo_tipo_para_receita?
		exercicio_inicial.present? && exercicio_inicial > 2018
	end

	def relatorio_de_resumo_financeiro_por_programas
		resumo_por_programa = []

		valor_por_exercicio = [
			valor_total_da_despesa_por_exercicio(exercicio_inicial).to_f,
			valor_total_da_despesa_por_exercicio(exercicio_inicial+1).to_f,
			valor_total_da_despesa_por_exercicio(exercicio_inicial+2).to_f,
			valor_total_da_despesa_por_exercicio(exercicio_final).to_f
		]

		Ppa::TipoDePrograma.all.each do |tipo_de_programa|
			valor_por_tipo_exercicio = [
				valor_total_da_despesa_por_exercicio_e_tipo_de_programa(exercicio_inicial, tipo_de_programa.id).to_f,
				valor_total_da_despesa_por_exercicio_e_tipo_de_programa(exercicio_inicial+1, tipo_de_programa.id).to_f,
				valor_total_da_despesa_por_exercicio_e_tipo_de_programa(exercicio_inicial+2, tipo_de_programa.id).to_f,
				valor_total_da_despesa_por_exercicio_e_tipo_de_programa(exercicio_final, tipo_de_programa.id).to_f
			]

			if valor_por_tipo_exercicio == 0
				resumo_por_programa << {
					estilo: {negrito: true},
					descricao: tipo_de_programa.nome,
					valor0: valor_por_tipo_exercicio[0].real, percentual0: (valor_por_tipo_exercicio[0] / valor_por_exercicio[0] * 100).round(2).real,
					valor1: valor_por_tipo_exercicio[1].real, percentual1: (valor_por_tipo_exercicio[1] / valor_por_exercicio[1] * 100).round(2).real,
					valor2: valor_por_tipo_exercicio[2].real, percentual2: (valor_por_tipo_exercicio[2] / valor_por_exercicio[2] * 100).round(2).real,
					valor3: valor_por_tipo_exercicio[3].real, percentual3: (valor_por_tipo_exercicio[3] / valor_por_exercicio[3] * 100).round(2).real
				}
			end

			programas.where(tipo_de_programa_id: tipo_de_programa.id).order(:codigo).each do |programa|
				if programa.projecoes_de_despesa_resumidas['total-geral'] > 0
					resultado = []
					dados = programa.total_por_exercicios
					dados = dados.each.map { |dado| {valor: dado['valor']} }.each_slice(4).to_a
					dados.each_with_index do |dado_por_exercicio, index_1|
						resultado[index_1] = {estilo: {tabulacao: {posicoes:[0], quantidade: 3}}, descricao: programa.nome}
						dado_por_exercicio.each_with_index do |dado, index_2|
							resultado[index_1][('valor'+index_2.to_s).to_sym] = dado[:valor].to_f.real
							resultado[index_1][('percentual'+index_2.to_s).to_sym] = (dado[:valor].to_f / valor_por_tipo_exercicio[index_2] * 100).round(2).real
						end
					end
					resumo_por_programa << resultado
				end
			end
		end

		resumo_por_programa << {
			estilo: {negrito: true},
			descricao: 'Total Geral',
			valor0: valor_por_exercicio[0].real, percentual0: '100,00',
			valor1: valor_por_exercicio[1].real, percentual1: '100,00',
			valor2: valor_por_exercicio[2].real, percentual2: '100,00',
			valor3: valor_por_exercicio[3].real, percentual3: '100,00'
		}
	end

	def iniciar_projecao
		params = {
			descricao: "Projeção de Receita #{self.exercicio_inicial} - #{self.exercicio_final}",
			exercicio_base_inicial: (self.exercicio_inicial.to_i - 4), exercicio_base_final: (self.exercicio_inicial.to_i - 2),
			exercicio_corrente: (self.exercicio_inicial.to_i - 1),
			exercicio_projecao_inicial: self.exercicio_inicial, exercicio_projecao_final: self.exercicio_final
		}

		self.create_projecao_de_receita(params)
	end

	private
	def validar_termos_de_uso_vazio
		if termos_de_uso == "" && habilitar_termos_de_uso == true
			errors[:termos_de_uso] << "Você não pode habilitar os termos de uso sem escreve-los."
			return false
		end

		return true
	end

	def sql_programas_invalidos
		%Q(
		SELECT ppa.id AS ppa_id,
		       programa.id AS programa_id,
		       programa.tipo_de_programa_id AS tipo_de_programa,
		       programa.tipo_de_programa_id::text || LPAD(programa.codigo::text, 3, '0') AS programa_codigo,
		       indicador.id as indicador_id,
		       objetivo.id AS objetivo_id,
			   objetivo.codigo AS objetivo_codigo,
		       natureza_da_iniciativa.codigo || LPAD(iniciativa.codigo::text, 3, '0') AS iniciativa_codigo,
		       iniciativa.id AS iniciativa_id,
			   meta.id AS meta_id,
			   meta.descricao AS meta_descricao,
		       meta_fisica.indice_de_referencia AS meta_fisica_quantidade
		  FROM ppa_ppas ppa
		  LEFT JOIN ppa_programas programa ON (programa.ppa_id = ppa.id)
		  JOIN ppa_tipos_de_programa tipo ON programa.tipo_de_programa_id = tipo.id
		  LEFT JOIN ppa_indicadores indicador ON (programa.id = indicador.programa_id)
		  LEFT JOIN ppa_objetivos objetivo ON (programa.id = objetivo.programa_id)
		  LEFT JOIN ppa_iniciativas iniciativa ON (objetivo.id = iniciativa.objetivo_id)
		  LEFT JOIN ppa_metas meta ON (objetivo.id = meta.objetivo_id)
		  LEFT JOIN ppa_naturezas_das_iniciativas natureza_da_iniciativa ON iniciativa.natureza_da_iniciativa_id = natureza_da_iniciativa.id
		  LEFT JOIN ppa_quantitativos meta_fisica ON (meta_fisica.meta_id = meta.id)
		 WHERE ppa.id = #{id}
		   AND (
				programa.nome IS NULL OR
				objetivo.descricao IS NULL OR
				iniciativa.descricao IS NULL OR
				meta_fisica.indice_de_referencia IS NULL OR
				CASE WHEN tipo.codigo = 1 THEN indicador.nome IS NULL OR meta.descricao IS NULL END
		 )
		 ORDER BY 1,2,3,4,5,6,7,8,9
		)
	end

	def diferenca_de_tempo_entre_exercicio_inicial_e_exercicio_final_deve_ser_4_anos
		if exercicio_inicial.present? && exercicio_final.present?
			unless exercicio_final - exercicio_inicial == 3
				errors.add(:exercicio_final, "deve ter 4 anos de diferença para o Exercício Inicial")
			end
		end
	end

	def somente_um_ppa_participativo_com_periodo_de_propostas_e_votacao
		if (abertura_do_periodo_de_propostas_changed? && fim_do_periodo_de_propostas_changed?) ||
			(abertura_do_periodo_de_votacao_changed? && fim_do_periodo_de_votacao_changed?)
			Ppa::Ppa.where.not(id: id).update_all(
			abertura_do_periodo_de_propostas: nil, fim_do_periodo_de_propostas: nil,
			abertura_do_periodo_de_votacao: nil, fim_do_periodo_de_votacao: nil
			)
		end
	end

	def sql_despesa_por_programa exercicio, tipo_de_programa_id=0
		%Q(
		SELECT sum(projecao.valor) as valor
		FROM ppa_programas programa
		JOIN ppa_tipos_de_programa tipo_de_programa ON programa.tipo_de_programa_id = tipo_de_programa.id
		JOIN ppa_projecoes_de_despesa projecao ON projecao.orcador_id = programa.id
		WHERE programa.ppa_id = #{id}
		AND projecao.exercicio = #{exercicio}
		AND (tipo_de_programa.id = #{tipo_de_programa_id} OR #{tipo_de_programa_id} = 0)
		AND orcador_type = 'Ppa::Programa'
		)
	end

	def sql_despesa_por_iniciativa exercicio, tipo_de_programa_id=0
		%Q(
		SELECT sum (projecao.valor) as valor
		FROM ppa_programas programa
		JOIN ppa_tipos_de_programa tipo_de_programa ON programa.tipo_de_programa_id = tipo_de_programa.id
		JOIN ppa_objetivos objetivo ON objetivo.programa_id = programa.id
		JOIN ppa_iniciativas iniciativa ON iniciativa.objetivo_id = objetivo.id
		JOIN ppa_projecoes_de_despesa projecao ON projecao.orcador_id = iniciativa.id
		WHERE programa.ppa_id = #{id}
		AND projecao.exercicio = #{exercicio}
		AND (tipo_de_programa.id = #{tipo_de_programa_id} OR #{tipo_de_programa_id} = 0)
		AND orcador_type = 'Ppa::Iniciativa'
		)
	end

	def valida_status_do_ppa
		outro_ppa_com_data_da_legislacao = Ppa::Ppa.where(exercicio_inicial: exercicio_inicial).aprovado.where.not(id: id)
		if outro_ppa_com_data_da_legislacao.present?
			errors.add(:data_da_legislacao, "Impossível finalizar este PPA caso exista outro PPA finalizado.")
		end
	end
end
