require 'httparty'

module ImportacaoTcm
	class ContabilidadeItensDaNotaFiscal
		@@host = 'https://api.tce.ce.gov.br/index.php/sim/1_0'

		class << self
			def importar codigo_do_municipio, exercicio
				orcamento = Orcamento.find_by(exercicio: exercicio)
				if orcamento.nil?
					ImportacaoTcm::Loa.importar( codigo_do_municipio, exercicio )
					orcamento = Orcamento.find_by( exercicio: exercicio )
				end

				::Loa::Orgao.where(orcamento_id: orcamento.id).order(:codigo).pluck(:id, :codigo).map do |orgao_id, codigo_do_orgao|
					itens_da_nota_fiscal = Array.new
					# puts "CARREGANDO ITENS DAS NOTAS FISCAIS DO ÓRGÃO #{codigo_do_orgao}..."
					::Loa::UnidadeOrcamentaria.where(orgao_id: orgao_id, importar_dependencias: true).order(:codigo).pluck(:codigo).map do |codigo_da_unidade_orcamentaria|
						dados_itens_da_nota_fiscal = importar_dados_itens_da_nota_fiscal( codigo_do_municipio, exercicio, codigo_do_orgao, codigo_da_unidade_orcamentaria )
						itens_da_nota_fiscal.concat(dados_itens_da_nota_fiscal) unless dados_itens_da_nota_fiscal.nil?
					end
					criar_itens_da_nota_fiscal( itens_da_nota_fiscal, orcamento, codigo_do_orgao ) if itens_da_nota_fiscal.size > 0
				end
			end

			def criar_itens_da_nota_fiscal dados_itens_da_nota_fiscal, orcamento, codigo_do_orgao
				progress_bar = ImportacaoTcm::Loa.barra_de_progresso( titulo: "ITENS DAS NOTAS FISCAIS DO ÓRGÃO #{codigo_do_orgao}", total: dados_itens_da_nota_fiscal.size ) unless Rails.env == "test"

				dados_itens_da_nota_fiscal.each do |item_da_nota|

					# Buscando e/ou criando Item(ns)
					unidade_de_medida_cadastrada = ::UnidadeDeMedida.where( "unaccent(descricao) ilike unaccent(?)", item_da_nota['unidade_compra'] ).first
					unidade_de_medida = if unidade_de_medida_cadastrada.present? && unidade_de_medida_cadastrada.descricao.parameterize.eql?(item_da_nota['unidade_compra'].parameterize)
																unidade_de_medida_cadastrada
															else
					 											::UnidadeDeMedida.create!( descricao: item_da_nota['unidade_compra'].downcase )
															end

					descricao = if item_da_nota['descricao1_item'].present?
												item_da_nota['descricao1_item'] + item_da_nota['descricao2_item']
											else
												"IMPORTADO DO TCM"
											end

					item = Base::Item.find_by( descricao: descricao, unidade_de_medida_id: unidade_de_medida.id)

					if item.blank?
						item = criar_item( descricao, unidade_de_medida )

					end

					# Buscando Liquidação(ões)
					empenho = ::Contabilidade::Empenho.find_by( orcamento_id: orcamento.id, numero_do_empenho: item_da_nota['numero_nota_empenho'] )

					# Criando Item(ns) do Empenho
					if empenho.present?
						liquidacao = ::Contabilidade::Liquidacao.find_by( empenho_id: empenho.id, data_da_liquidacao: item_da_nota['data_liquidacao'].to_date )

						item_do_empenho = ::Contabilidade::ItemDoEmpenho.find_by( empenho_id: empenho.id, item_id: item.id)
						if item_do_empenho.blank?
							item_do_empenho = criar_item_do_empenho( empenho, item, item_da_nota['numero_quantidade_comprada'].to_f, item_da_nota['valor_unitario_item'].to_f, item_da_nota['valor_total_item'].to_f )

						else
							inclui_quantidade_valor_e_total( item_do_empenho, item_da_nota['numero_quantidade_comprada'].to_f, item_da_nota['valor_unitario_item'].to_f, item_da_nota['valor_total_item'].to_f )

						end

						# Criando Item(ns) da Nota Fiscal
						if liquidacao.present?
							item_da_nota_fiscal = ::Contabilidade::ItemDaNotaFiscal.find_by( liquidacao_id: liquidacao.id, item_id: item_do_empenho.try(:item).try(:id) )

							if item_da_nota_fiscal.blank?
								criar_item_da_nota_fiscal( liquidacao, item_do_empenho, item_da_nota['numero_quantidade_comprada'].to_f, item_da_nota['valor_unitario_item'].to_f, item_da_nota['valor_total_item'].to_f )

							else
								inclui_quantidade_valor_e_total( item_da_nota_fiscal, item_da_nota['numero_quantidade_comprada'].to_f, item_da_nota['valor_unitario_item'].to_f, item_da_nota['valor_total_item'].to_f )

							end
						end
					end

					progress_bar.increment unless Rails.env == "test"
				end
			end

			def importar_dados_itens_da_nota_fiscal codigo_do_municipio, exercicio, codigo_do_orgao, codigo_da_unidade_orcamentaria
				begin
					response = HTTParty.get("#{@@host}/itens_notas_fiscais.xml?codigo_municipio=#{codigo_do_municipio}&exercicio_orcamento=#{exercicio}00&codigo_orgao=#{codigo_do_orgao}&codigo_unidade=#{codigo_da_unidade_orcamentaria}")
					dados_itens_da_nota_fiscal = Hash.from_xml(response.body.encode(Encoding::UTF_8))['rsp']['itens_notas_fiscais']
					if dados_itens_da_nota_fiscal.is_a?(Array)
						return dados_itens_da_nota_fiscal
					else
						if dados_itens_da_nota_fiscal.nil?
							return nil
						else
							return dados_itens_da_nota_fiscal = [ dados_itens_da_nota_fiscal ]
						end
					end
				rescue
					puts "Página não encontrada, tentando novamente..."
					sleep 5
					importar_dados_itens_da_nota_fiscal codigo_do_municipio, exercicio, codigo_do_orgao, codigo_da_unidade_orcamentaria
					return nil
				end
			end
		end

		def self.criar_item descricao, unidade_de_medida
			categoria = Base::Categoria.find_or_create_by(titulo: "GERAL", tipo: "produto")
			subcategoria = Base::Categoria.find_or_create_by(titulo: "IMPORTADO DO TCM", tipo: "produto", categoria_superior_id: categoria.id)

			item = ::Base::Item.new(
				descricao: descricao,
				unidade_de_medida_id: unidade_de_medida.id,
				categoria_id: subcategoria.id,
			)
			item.save!(validate: false)

			return item
		end

		def self.criar_item_do_empenho empenho, item, quantidade, valor_unitario, total
			item_do_empenho = ::Contabilidade::ItemDoEmpenho.new(
				empenho_id: empenho.id,
				item_id: item.id,
				quantidade: quantidade,
				valor_unitario: valor_unitario,
				total: total
			)

			item_do_empenho.save!(validate: false)

			return item_do_empenho
		end

		def self.criar_item_da_nota_fiscal liquidacao, item_do_empenho, quantidade, valor_unitario, total
			item_da_nota_fiscal = ::Contabilidade::ItemDaNotaFiscal.new(
				liquidacao_id: liquidacao.id,
				item_id: item_do_empenho.try(:item).try(:id),
				quantidade: quantidade,
				valor_unitario: valor_unitario,
				total: total
			)

			item_da_nota_fiscal.save!(validate: false)

			return item_da_nota_fiscal
		end

		def self.inclui_quantidade_valor_e_total item, quantidade, valor_unitario, total
			item.quantidade += quantidade
			item.valor_unitario += valor_unitario
			item.total += total
			item.save!(validate: false)
		end

		private_class_method :criar_item
		private_class_method :criar_item_do_empenho
		private_class_method :criar_item_da_nota_fiscal
		private_class_method :inclui_quantidade_valor_e_total
	end
end
