class DuplicarOrcamento
	def initialize orcamento, orcamento_anterior
		@orcamento = orcamento
		@orcamento_anterior = orcamento_anterior
	end

	def perform
		copia_programas
		copia_orgaos
	end

	def copia_orgaos
		puts "COPIANDO ORGAOS..."
		bar = RakeProgressbar.new(@orcamento_anterior.orgaos.count)

		@orcamento_anterior.orgaos.each do |orgao_antigo|
			atributos = orgao_antigo.attributes.except("id", "orcamento_id", "tipo_de_unidade_administrativa_id", "status_do_orcamento", "arquivo_id", "created_at", "updated_at")
			atributos.merge(importado_do_orcamento_anterior: true)
			orgao = @orcamento.orgaos.new atributos
			orgao.tipo_de_unidade_administrativa = @orcamento.tipos_de_unidades_administrativas.find_by(codigo: orgao_antigo.tipo_de_unidade_administrativa.codigo)
			orgao.save(validate: false)

			# raise ActiveRecord::Rollback unless orgao.persisted?
			copia_unidades_orcamentarias(orgao_antigo, orgao)
			bar.inc
		end

		bar.finish
	end

	def copia_unidades_orcamentarias orgao_antigo, orgao
		orgao_antigo.unidades_orcamentarias.each do |uo_antiga|
			atributos = uo_antiga.attributes.except("id", "orcamento_id", "created_at", "updated_at", "status_do_orcamento", "arquivo_id", "orgao_id", "tipo_de_administracao_id", "tipo_de_unidade_administrativa_id")
			uo = orgao.unidades_orcamentarias.new atributos
			uo.tipo_de_administracao = @orcamento.tipos_de_administracao.find_by_codigo(uo_antiga.tipo_de_administracao.codigo)
			uo.tipo_de_unidade_administrativa = @orcamento.tipos_de_unidades_administrativas.find_by_codigo(uo_antiga.tipo_de_unidade_administrativa.codigo)

			ug_antiga = uo_antiga.unidade_gestora
			atributos_ug = ug_antiga.attributes.except("id", "orcamento_id", "created_at", "updated_at", "status_do_orcamento")
			ug = @orcamento.unidades_gestoras.find_or_create_by(atributos_ug)
			ug.save(validate: false)
			uo.unidade_gestora = ug
			uo.save(validate: false)

			#raise ActiveRecord::Rollback unless uo.persisted?
			copia_subacoes uo_antiga, uo
			copia_agentes_publicos uo_antiga, uo
			#copia_permissoes_dos_usuarios uo_antiga, uo
			#copia_gestores ug_antiga, ug
		end
	end

	def copia_agentes_publicos uo_antiga, uo
		uo_antiga.agente_publico.each do |agente_antigo|
			# atributos = agente_antigo.attributes.except("id", "created_at", "updated_at", "status_do_orcamento", "unidade_orcamentaria_id")
			# agente = uo.agente_publico.new(atributos)
			agente = agente_antigo.dup
			agente.unidade_orcamentaria_id = uo.id
			agente.save(validate: false)
			raise ActiveRecord::Rollback unless agente.persisted?

			if agente_antigo.ordenador_de_despesa.present?
				ordernador = agente_antigo.ordenador_de_despesa.dup
				# atributos = agente_antigo.ordenador_de_despesa.attributes.except("id", "created_at", "updated_at", "status_do_orcamento", "agente_publico_id", "unidade_orcamentaria_id")
				begin
					ordernador.agente_publico_id = agente.id
					ordernador.unidade_orcamentaria_id = uo.id
					ordernador.save(validate: false)
				rescue => exception
					p "Erro ao copiar agente publico: #{exception.message}"
				end
			end
		end
	end	

	def copia_permissoes_dos_usuarios uo_antiga, uo
		uo_antiga.unidades_orcamentarias_por_usuario.each do |uo_por_usuario_antiga|
			begin
				uo.unidades_orcamentarias_por_usuario.create!(usuario: uo_por_usuario_antiga.usuario)
			rescue => exception
				p "Erro ao copiar permissoes de usuario: #{exception.message}"
			end
		end
	end

	# def copia_gestores ug_antiga, ug
	# 	ug_antiga.gestores.each do |gestor|
	# 		atributos = gestor.attributes.except("id", "created_at", "updated_at", "unidade_gestora_id")
	# 		begin
	# 			gestor = ug.gestores.new(atributos.merge(unidade_gestora_id: ug.id))
	# 			gestor.save(validate: false)
	# 		rescue => exception
	# 			p "Erro ao copiar gestor #{exception.message}"
	# 		end
	# 	end
	# end

	def copia_programas
		puts "COPIANDO PROGRAMAS..."
		bar = RakeProgressbar.new(@orcamento_anterior.programas_de_governo.count)

		@orcamento_anterior.programas_de_governo.each do |programa_antigo|
			atributos = programa_antigo.attributes.except("id", "orcamento_id", "created_at", "updated_at", "status_do_orcamento", "arquivo_id")
			programa = @orcamento.programas_de_governo.new atributos
			programa.save(validate: false)
			raise ActiveRecord::Rollback unless programa.persisted?

			copia_acoes(programa_antigo, programa)
			bar.inc
		end

		bar.finish
	end

	def copia_acoes programa_antigo, programa
		programa_antigo.acoes.each do |acao_antiga|
			atributos = acao_antiga.attributes.except("id", "orcamento_id", "programa_de_governo_id", "natureza_da_acao_id", "created_at", "updated_at", "status_do_orcamento")
			acao = programa.acoes.new atributos
			acao.natureza_da_acao = @orcamento.naturezas_da_acao.find_by_codigo(acao_antiga.natureza_da_acao.codigo)
			acao.save(validate: false)
			raise ActiveRecord::Rollback unless acao.persisted?
		end
	end

	def copia_subacoes uo_antiga, uo
		uo_antiga.subacoes.each do |subacao_antiga|
			atributos = subacao_antiga.attributes.except("id", "acao_id", "funcao_id", "subfuncao_id", "created_at", "updated_at", "status_do_orcamento", "arquivo_id")
			subacao = uo.subacoes.new atributos
			subacao.funcao = @orcamento.funcoes.find_by_codigo(subacao_antiga.funcao.codigo)
			subacao.subfuncao = @orcamento.subfuncoes.find_by_codigo(subacao_antiga.subfuncao.codigo)
			subacao.tipo_de_orcamento = @orcamento.tipos_de_orcamento.find_by_numero(subacao_antiga.tipo_de_orcamento.numero)
			subacao.acao = @orcamento.acoes.joins(:natureza_da_acao).find_by(codigo: subacao_antiga.acao.try(:codigo), base_naturezas_das_acoes: {codigo: subacao_antiga.acao.try(:natureza_da_acao).try(:codigo)})
			subacao.fixacao_da_despesa = nil unless @orcamento.importar_despesas
			subacao.data_de_envio_ao_sim = Date.new(uo.orgao.orcamento.exercicio, 1, 1)
			subacao.save(validate: false)
			raise ActiveRecord::Rollback unless subacao.persisted?

			if @orcamento_anterior.ppa_id == @orcamento.ppa_id
				subacao_antiga.metas_fisicas.each do |meta_fisica_antiga|
					atributos = meta_fisica_antiga.attributes.except("id", "subacao_id", "created_at", "updated_at", "status_do_orcamento")
					begin
						subacao.metas_fisicas.create!(atributos)
					rescue => exception
						p "Erro ao copiar subacao: #{exception.message}"
					end
				end
			end

			importar_elementos_de_despesa_por_subacao subacao_antiga, subacao 
		end
	end

	def importar_elementos_de_despesa_por_subacao(subacao_antiga, subacao)
		elementos_de_despesa_novos = @orcamento.elementos_de_despesa.index_by(&:codigo)
		subacao_antiga.elementos_de_despesa_por_subacao.each do |elemento_por_subacao_antigo|
			elemento_de_despesa_novo = elementos_de_despesa_novos[elemento_por_subacao_antigo.elemento_de_despesa.codigo]
			if elemento_de_despesa_novo.present?
				elemento_de_despesa_por_subacao = subacao.elementos_de_despesa_por_subacao.find_or_create_by!(elemento_de_despesa: elemento_de_despesa_novo)

				importar_orcamentos_da_despesa(elemento_por_subacao_antigo, elemento_de_despesa_por_subacao)
			end
		end
	end

	def importar_orcamentos_da_despesa elemento_de_despesa_por_subacao_antigo, elemento_de_despesa_por_subacao
		fontes_de_recursos = Base::FonteDeRecursos.where(modulo: @orcamento).all

		elemento_de_despesa_por_subacao_antigo.orcamentos_da_despesa.each do |orcamento_da_despesa|
			begin
				fonte = fontes_de_recursos.find { |i| i.codigo_completo == orcamento_da_despesa.fonte_de_recursos.codigo_completo }
				if fonte.present? && fonte.codigo_completo[0] == "1"
					# CASO QUEIRA IMPORTAR COM VALORES É SÓ ALTERAR ABAIXO PARA O VALOR ANTERIOR DO ORÇAMENTO DA DESPESA
					novo_orcamento_da_despesa = elemento_de_despesa_por_subacao.orcamentos_da_despesa.new(
						fonte_de_recursos_id: fonte.id,
						valor: 0,
						valor_empenhado: 0,
						status_do_orcamento: 0,
						valor_orcado: 0,
						de_credito_adicional: false,
						iduso: 0
					)
					novo_orcamento_da_despesa.save
				end
			rescue => exception
				raise ActiveRecord::Rollback
			end
		end
	end
end
