class Ppa::Convenio < ApplicationRecord
	has_paper_trail

	attr_accessor :orgao_id, :area_tematica_id

	belongs_to :ppa
	belongs_to :unidade_orcamentaria
	belongs_to :sub_area_tematica, class_name: 'Ppa::SubAreaTematica'
	belongs_to :receita_corrente, class_name: "Projecao::Receita", inverse_of: :convenios
	belongs_to :receita_de_capital, class_name: "Projecao::Receita", inverse_of: :convenios
	has_one :contabilidade_convenio, class_name: "Contabilidade::Convenio"

	has_many :valores_do_convenio, dependent: :destroy, inverse_of: :convenio

	after_create :criar_valores_do_convenio_para_cada_exercicio_do_ppa

	after_update :atualiza_calculo_por_exercicio_das_receitas, if: Proc.new { receita_corrente_id.present? || receita_de_capital_id.present? }

	before_destroy :atualiza_calculo_por_exercicio_das_receitas, if: Proc.new { receita_corrente_id.present? || receita_de_capital_id.present? }

	validates_presence_of :ppa_id, :objeto, :valor,:status
	validates_length_of :numero_do_convenio, maximum: 10

	validates_presence_of :receita_corrente_id, if: Proc.new { receita_de_capital_id.blank?}, :message => 'No mínimo uma receita corrente ou de capital deve ser escolhida.'
	validates_presence_of :receita_de_capital_id, if: Proc.new { receita_corrente_id.blank?}, :message => 'No mínimo uma receita corrente ou de capital deve ser escolhida.'

	validate :categorias_das_receitas
	validate :receita_nao_deve_ter_calculos_de_projecao_associados

	accepts_nested_attributes_for :valores_do_convenio

	before_update :limpar_valores_se_receita_vazia_apos_atualizar

	enum esfera: {
		estadual: 0,
		federal: 1
	}

	enum status: {
		"em execução": 0,
		"em cadastro": 1,
		"nova demanda": 2
	}

	def receitas
		[try(:receita_corrente), try(:receita_de_capital)].compact
	end

	def tem_receitas?
		receitas.any?
	end

	def self.dados_unico_convenio convenio
		dados_do_relatorio = []
		orgao = []
		unidade_orcamentaria  = []
		esfera  = []
		concedente  = []
		subarea  = []
		valor = []
		status = []

		status << {
			titulo: 'Status',
			valor: convenio.status.humanize,
		}

		valor << {
			titulo: 'Valor',
			valor: convenio.valor.real_contabil.to_s,
		}

		orgao << {
			titulo: 'Orgão',
			orgao: convenio.try(:unidade_orcamentaria).try(:orgao).try(:codigo_e_nome).to_s,
		}

		unidade_orcamentaria << {
			titulo: 'Unidade Orçamentária',
			unidade_orcamentaria: convenio.try(:unidade_orcamentaria).try(:codigo_completo_e_nome).to_s,
		}

		esfera << {
			titulo:'Esfera',
			esfera: convenio.try(:esfera).try(:titleize),
		}

		concedente << {
			titulo: 'Concedente',
			concedente: convenio.concedente,
		}

		subarea << {
			titulo: 'Sub Área Temática',
			subarea: convenio.sub_area_tematica.try(:nome),
		}

		dados_do_relatorio << status
		dados_do_relatorio << valor
		dados_do_relatorio << orgao
		dados_do_relatorio << unidade_orcamentaria
		dados_do_relatorio << esfera
		dados_do_relatorio << concedente
		dados_do_relatorio << subarea

	end

	def self.dados_relatorio_receita ppa_atual,convenio
		dados_do_relatorio = []
		dados_do_relatorio_corrente = []
		dados_do_relatorio_capital = []
		total_convenio = []

		if convenio.receita_corrente.present?
			dados_do_relatorio_corrente << {
				receita: convenio.receita_corrente.codigo_formatado_e_descricao,
				exercicio1: convenio.valores_do_convenio.convenios_correntes.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial)}.valor.real.to_s,
				exercicio2: convenio.valores_do_convenio.convenios_correntes.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 1 )}.valor.real.to_s,
				exercicio3: convenio.valores_do_convenio.convenios_correntes.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 2)}.valor.real.to_s,
				exercicio4: convenio.valores_do_convenio.convenios_correntes.find{|d| d.exercicio.eql?(ppa_atual.exercicio_final)}.valor.real.to_s,
			}

			dados_do_relatorio << dados_do_relatorio_corrente
		end

		if convenio.receita_de_capital.present?
			dados_do_relatorio_capital << {
				receita: convenio.receita_de_capital.codigo_formatado_e_descricao,
				exercicio1: convenio.valores_do_convenio.convenios_de_capital.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial)}.valor.real.to_s,
				exercicio2: convenio.valores_do_convenio.convenios_de_capital.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 1 )}.valor.real.to_s,
				exercicio3: convenio.valores_do_convenio.convenios_de_capital.find{|d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 2)}.valor.real.to_s,
				exercicio4: convenio.valores_do_convenio.convenios_de_capital.find{|d| d.exercicio.eql?(ppa_atual.exercicio_final)}.valor.real.to_s,
			}

			dados_do_relatorio << dados_do_relatorio_capital
		end


		total_convenio << {
			total: 'Total de Convênio',
			exercicio1: convenio.valores_do_convenio.select { |d| d.exercicio.eql?(ppa_atual.exercicio_inicial) }.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }.real_contabil,
			exercicio2: convenio.valores_do_convenio.select { |d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 1) }.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }.real_contabil,
			exercicio3: convenio.valores_do_convenio.select { |d| d.exercicio.eql?(ppa_atual.exercicio_inicial + 2) }.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }.real_contabil,
			exercicio4: convenio.valores_do_convenio.select { |d| d.exercicio.eql?(ppa_atual.exercicio_final) }.inject(0){ |total, valor_do_convenio| total + valor_do_convenio.valor.to_f }.real_contabil,
			estilo: { negrito: true }
		}

		dados_do_relatorio << total_convenio

		return dados_do_relatorio
	end

	def self.resumo_de_previsao_de_convenios ppa_id, unidade_orcamentaria
		if unidade_orcamentaria.present?
			return resumo_de_previsao_de_convenios_por_unidade_orcamentaria( ppa_id )
		end
	end

	def atualiza_calculo_por_exercicio_das_receitas
		if self.receita_corrente_id
			raise "Não foi possível atualizar cálculo para receita corrente" unless receita_corrente.atualizar_valor_de_convenio
		end

		if self.receita_de_capital_id
			raise "Não foi possível atualizar cálculo para receita de capital" unless receita_de_capital.atualizar_valor_de_convenio
		end

		if self.receita_de_capital_id_changed? && receita_de_capital_id_was.present?
			receita_de_capital_antiga = Projecao::Receita.find(receita_de_capital_id_was)
			raise "Não foi possível atualizar cálculo para receita de capital" unless receita_de_capital_antiga.atualizar_valor_de_convenio
		end

		if self.receita_corrente_id_changed? && receita_corrente_id_was.present?
			receita_corrente_antiga = Projecao::Receita.find(receita_corrente_id_was)
			raise "Não foi possível atualizar cálculo para receita de capital" unless receita_corrente_antiga.atualizar_valor_de_convenio
		end
	end

	def self.relatorio_todos_os_convenios ppa_atual
		convenios = ppa_atual.convenios
		resultado = []
		total = []

		convenios.each do |convenio|
			resultado.push({objeto: convenio.objeto, numero: convenio.numero_do_convenio, status: convenio.status, valor:convenio.valor.real.to_s} )
			total.push(convenio.valor.to_int)
		end

		total_final = total.sum.real.to_s
		resultado.push({estilo: {negrito: true}, objeto: 'TOTAL',numero: '', status: '', valor:total_final})
		return resultado
	end

	def self.relatorio_por_unidade_orcamentaria ppa_atual, unidade_orcamentaria
		convenios = ppa_atual.convenios.where(unidade_orcamentaria_id: unidade_orcamentaria)
		resultado = []
		convenios.each do |convenio|
			resultado.push({objeto: convenio[:objeto], valor:convenio[:valor].real.to_s} )
		end
		return resultado
	end

	def self.total_por_unidade_orcamentaria ppa_atual, unidade_orcamentaria
		convenios = ppa_atual.convenios.where(unidade_orcamentaria_id: unidade_orcamentaria)
		total = []


			convenios.each do |convenio|
				resultado.push({objeto: convenio[:objeto], valor:convenio[:valor].real.to_s} )
				total.push(convenio.valor.to_int)
			end
			total_final = total.sum.real.to_s
			resultado.push({estilo: {negrito: true}, objeto: 'TOTAL', valor:total_final})

			return resultado

	end

	def self.relatorio_por_status ppa_atual, status
		convenios = ppa_atual.convenios.where(status: status)
		resultado = []
		convenios.each do |convenio|
			resultado.push({objeto: convenio.objeto, valor:convenio.valor.real.to_s} )
		end
		return resultado
	end

	def self.total_por_status ppa_atual, status
		convenios = ppa_atual.convenios.where(status: status)
		total = []
		convenios.each do |convenio|
			resultado.push({objeto: convenio.objeto, valor:convenio.valor.real.to_s} )
			total.push(convenio.valor.to_int)
		end
		total_final = total.sum.real.real.to_s
		resultado.push({estilo: {negrito: true}, objeto: 'TOTAL', valor:total_final})
		return resultado
	end

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

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

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

	def valido?
		valor == valores_do_convenio.sum(:valor)
	end

	private
	def categorias_das_receitas
		errors.add(:receita_corrente_id, "deve ser de uma receita corrente") if self.receita_corrente && self.try(:receita_corrente).try(:categoria_economica) != "1"
		errors.add(:receita_de_capital_id, "deve ser de uma receita de capital") if self.receita_de_capital && self.try(:receita_de_capital).try(:categoria_economica) != "2"
	end

	def receita_nao_deve_ter_calculos_de_projecao_associados
		errors.add(:receita_corrente_id, "essa receita já foi projetada por meio de cálculo.") if self.receita_corrente && self.try(:receita_corrente).try(:receitas_dos_calculos_de_projecao).try(:any?)
		errors.add(:receita_de_capital_id, "essa receita já foi projetada por meio de cálculo") if self.receita_de_capital && self.try(:receita_de_capital).try(:receitas_dos_calculos_de_projecao).try(:any?)
	end

	def self.resumo_de_previsao_de_convenios_por_funcao ppa_id
		dados_do_relatorio = []
		dados_de_previsao_de_convenios_correntes = []
		dados_de_previsao_de_convenios_de_capital = []

		ppa = Ppa::Ppa.find( ppa_id )
		ppa.funcoes.each { |funcao|
			if funcao.total_previsao_de_convenios_correntes.to_f > 0
				dados_de_previsao_de_convenios_correntes << {
					especificacao: funcao.codigo_e_nome,
					exercicio1: funcao.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial ).contabil,
					exercicio2: funcao.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
					exercicio3: funcao.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
					exercicio4: funcao.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_final ).contabil,
					total: 			funcao.total_previsao_de_convenios_correntes.contabil,
					estilo: {tabulacao: {posicoes:[0], quantidade: 3}}
				}
			end

			if funcao.total_previsao_de_convenios_de_capital.to_f > 0
				dados_de_previsao_de_convenios_de_capital << {
					especificacao: funcao.codigo_e_nome,
					exercicio1: funcao.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial ).contabil,
					exercicio2: funcao.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
					exercicio3: funcao.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
					exercicio4: funcao.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_final ).contabil,
					total: 			funcao.total_previsao_de_convenios_de_capital.contabil,
					estilo: {tabulacao: {posicoes:[0], quantidade: 3}}
				}
			end
		}

		dados_do_relatorio << {
			especificacao: 'CONV. CORRENTES',
			exercicio1: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_final ).contabil,
			total: 			ppa.total_previsao_de_convenios_correntes.contabil,
			estilo: { negrito: true }
		}
		dados_do_relatorio << dados_de_previsao_de_convenios_correntes

		dados_do_relatorio << {
			especificacao: 'CONV. DE CAPITAL',
			exercicio1: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_final ).contabil,
			total: 			ppa.total_previsao_de_convenios_de_capital.contabil,
			estilo: { negrito: true }
		}
		dados_do_relatorio << dados_de_previsao_de_convenios_de_capital

		dados_do_relatorio << {
			especificacao: 'TOTAL DE CONVÊNIOS',
			exercicio1: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_final ).contabil,
			total: ppa.total_geral_de_previsao_de_convenios.contabil,
			estilo: { negrito: true }
		}

		return dados_do_relatorio.flatten
	end

	def self.resumo_de_previsao_de_convenios_por_unidade_orcamentaria ppa_id
		dados_do_relatorio = []
		dados_de_previsao_de_convenios_correntes = []
		dados_de_previsao_de_convenios_de_capital = []

		ppa = Ppa::Ppa.find( ppa_id )
		ppa.unidades_orcamentarias.each { |unidade_orcamentaria|
			if unidade_orcamentaria.total_previsao_de_convenios_correntes.to_f > 0
				dados_de_previsao_de_convenios_correntes << {
					especificacao: unidade_orcamentaria.sigla.to_s,
					exercicio1: unidade_orcamentaria.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial ).contabil,
					exercicio2: unidade_orcamentaria.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
					exercicio3: unidade_orcamentaria.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
					exercicio4: unidade_orcamentaria.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_final ).contabil,
					total: 		unidade_orcamentaria.total_previsao_de_convenios_correntes.contabil,
					estilo: {tabulacao: {posicoes:[0], quantidade: 3}}
				}
			end

			if unidade_orcamentaria.total_previsao_de_convenios_de_capital.to_f > 0
				dados_de_previsao_de_convenios_de_capital << {
					especificacao: unidade_orcamentaria.sigla.to_s,
					exercicio1: unidade_orcamentaria.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial ).contabil,
					exercicio2: unidade_orcamentaria.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
					exercicio3: unidade_orcamentaria.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
					exercicio4: unidade_orcamentaria.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_final ).contabil,
					total: 			unidade_orcamentaria.total_previsao_de_convenios_de_capital.contabil,
					estilo: {tabulacao: {posicoes:[0], quantidade: 3}}
				}
			end
		}

		dados_do_relatorio << {
			especificacao: 'CONV. CORRENTES',
			exercicio1: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_previsao_de_convenios_correntes_por_exercicio( ppa.exercicio_final ).contabil,
			total: 			ppa.total_previsao_de_convenios_correntes.contabil,
			estilo: { negrito: true }
		}

		dados_do_relatorio << dados_de_previsao_de_convenios_correntes

		dados_do_relatorio << {
			especificacao: 'CONV. DE CAPITAL',
			exercicio1: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_previsao_de_convenios_de_capital_por_exercicio( ppa.exercicio_final ).contabil,
			total: 		ppa.total_previsao_de_convenios_de_capital.contabil,
			estilo: { negrito: true }
		}
		dados_do_relatorio << dados_de_previsao_de_convenios_de_capital

		dados_do_relatorio << {
			especificacao: 'TOTAL DE CONVÊNIOS',
			exercicio1: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial ).contabil,
			exercicio2: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial + 1 ).contabil,
			exercicio3: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_inicial + 2 ).contabil,
			exercicio4: ppa.total_geral_de_previsao_de_convenios_por_exercicio( ppa.exercicio_final ).contabil,
			total: 			ppa.total_geral_de_previsao_de_convenios.contabil,
			estilo: { negrito: true }
		}

		return dados_do_relatorio.flatten
	end

	def criar_valores_do_convenio_para_cada_exercicio_do_ppa
		if ppa.present?
			ppa.periodo.each { |exercicio|
				criar_valor_do_convenio( Base::TipoDeDespesa.despesa_corrente, exercicio )
				criar_valor_do_convenio( Base::TipoDeDespesa.despesa_de_capital, exercicio )
			}
		end
	end

	def criar_valor_do_convenio( tipo_de_despesa, exercicio )
		if tipo_de_despesa.present?
			Ppa::ValorDoConvenio.create!(
				convenio_id: self.id,
				tipo_de_despesa_id: tipo_de_despesa.id,
				exercicio: exercicio,
				valor: 0
			)
		end
	end

	def limpar_valores_se_receita_vazia_apos_atualizar
		if !self.receita_corrente_id.present?
			self.valores_do_convenio.convenios_correntes.each do |convenio_corrente|
				convenio_corrente[:valor] = 0.00
				convenio_corrente.save(validate:false)
			end
		end

		if !self.receita_de_capital_id.present?
			self.valores_do_convenio.convenios_de_capital.each do |convenio_capital|
				convenio_capital[:valor] = 0.00
				convenio_capital.save(validate:false)
			end
		end
	end
end
