require 'active_support/concern'

module Tcm::NotaFiscalConcern extend ActiveSupport::Concern
	# NF_____.DCD
	# ARQUIVO 602

	def pesquisa_notas_fiscais
		status_a_utilizar_lq = [2, 5, 6, 8]
		tipos_a_utilizar_nf = [1, 2, 3, 4, 5, 6]

		notas_fiscais = Contabilidade::NotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]])
			.where('contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_notas_fiscais.tipo_de_emissao is not null AND contabilidade_liquidacoes.status in (2,5,6,8) and tipo_da_nota between 1 and 6 AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao <= ? AND contabilidade_liquidacoes.restos_a_pagar <> TRUE', self.lote.data_referencia, self.lote.data_referencia.end_of_month)
			.where('contabilidade_liquidacoes.status in (?)', status_a_utilizar_lq).where('contabilidade_notas_fiscais.tipo_da_nota in (?)', tipos_a_utilizar_nf)
			.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.lote.poder_associado)

		notas_fiscais_de_rp = Contabilidade::NotaFiscal.joins(liquidacao: [empenho: [orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: [unidade_orcamentaria: :tipo_de_unidade_administrativa]]]]])
			.where('contabilidade_liquidacoes.data_da_liquidacao is not null AND contabilidade_notas_fiscais.tipo_de_emissao is not null AND contabilidade_liquidacoes.status in (2,5,6,8) and tipo_da_nota between 1 and 6 AND contabilidade_liquidacoes.restos_a_pagar = true AND contabilidade_liquidacoes.data_da_liquidacao >= ? AND contabilidade_liquidacoes.data_da_liquidacao <= ?', self.lote.data_referencia, self.lote.data_referencia.end_of_month)
			.where('contabilidade_liquidacoes.status in (?)', status_a_utilizar_lq).where('contabilidade_notas_fiscais.tipo_da_nota in (?)', tipos_a_utilizar_nf)
			.where('base_tipos_de_unidades_administrativas.poder_associado = ?', self.lote.poder_associado)
			.select{|nf| nf.liquidacao.eh_processada? == false}

		return notas_fiscais + notas_fiscais_de_rp
	end

	def gerar_notas_fiscais
		# pesquisar objetos
		objetos = self.pesquisa_notas_fiscais
		classe_do_objeto = 'Contabilidade::NotaFiscal'
		tipo_de_poder = Tcm::Linha.tipos_de_poder[self.lote.tipo_de_poder]

		# limpar arquivo
		ActiveRecord::Base.connection.execute("DELETE FROM tcm_linhas WHERE modulo_type = '#{classe_do_objeto}' and tipo_de_poder = #{tipo_de_poder} and arquivo_referencia = '#{self.nome}'")

		self.carrega_dependencias_para_notas_fiscais

		linhas = []
		conteudo = ""
		objetos.group_by{|nf| [nf.liquidacao.empenho_id, nf.liquidacao.data_da_liquidacao , nf.liquidacao.tipo_da_folha || '' , nf.attributes.except("id", "liquidacao_id","tipo_de_desconto", "valor_de_desconto", "cfop_id", "created_at", "updated_at", "orcamentario_iss", "extraorcamentario_iss", "orcamentario_inss_pj", "extraorcamentario_inss_pj", "extraorcamentario_irpj", "orcamentario_irpj", "extraorcamentario_inss_pf","orcamentario_irpf", "extraorcamentario_irpf", "arquivo_id")]}.each do |agrupamento, nfs|
			objeto = nfs.min_by(&:id)
			linha = self.nota_fiscal_to_sim(nfs)
			conteudo << linha
			conteudo << "\r\n"
			linhas << Tcm::Linha.new(modulo_id: objeto.id, modulo_type: objeto.class.name, arquivo_referencia: self.nome , conteudo: linha, tipo_de_poder: tipo_de_poder)
			nfs.each{|nf| nf.update_column(:arquivo_id, self.id)}
		end
		self.update_columns(conteudo: conteudo, classe: classe_do_objeto)
		Tcm::Linha.import linhas
	end

	def carrega_dependencias_para_notas_fiscais
		@configuracao = Configuracao.first
		@orcamentos = Orcamento.all.map(&:attributes).map(&:symbolize_keys)
	end

	def nota_fiscal_to_sim(notas_fiscais)
		begin
			nota_fiscal = notas_fiscais.min_by(&:id)
			val_liquuido_total = notas_fiscais.map{|nf| nf.valor_liquido.to_f}.sum
			val_desconto_total = notas_fiscais.map{|nf| nf.valor_de_desconto.to_f}.sum
			val_total_nfs = notas_fiscais.map{|nf| nf.liquidacao.valor.to_f}.sum
			aliquitota = notas_fiscais.map{|nf| nf.liquidacao.retencao_de_iss.aliquota.to_f rescue 0}.sum
			base_calculo = notas_fiscais.map{|nf| nf.liquidacao.retencao_de_iss.base_de_calculo.to_f rescue 0}.sum
			exercicio_do_orcamento = nota_fiscal.liquidacao.empenho.orcamento.exercicio.to_s
			valor_descontos = nota_fiscal.try(:valor_de_desconto).to_f
			valor_liquido = (nota_fiscal.liquidacao.valor.to_f - valor_descontos)
			incricao =
				if nota_fiscal.mercadoria? || nota_fiscal.mercadoria_produtor? || nota_fiscal.mercadoria_e_servico?
					nota_fiscal.liquidacao.empenho.try(:pessoa).try(:inscricao_estadual)
				elsif nota_fiscal.servico?
					nota_fiscal.liquidacao.empenho.try(:pessoa).try(:inscricao_municipal)
				else
					""
				end
			

			texto = ""
			texto << "602".sim_preenche(3) + "," #1
			texto << @configuracao.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
			texto << exercicio_do_orcamento + "00" + "," #3
			texto << nota_fiscal.liquidacao.unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #4
			texto << nota_fiscal.liquidacao.unidade_orcamentaria.codigo.codigo_uo_to_sim + "," #5
			texto << nota_fiscal.liquidacao.empenho.data_do_empenho.to_date.sim_data + "," #6
			texto << nota_fiscal.liquidacao.empenho.numero_do_empenho.sim_limite(8) + "," #7
			texto << nota_fiscal.liquidacao.data_da_liquidacao.sim_data + "," #8
			texto << nota_fiscal.tipo_da_nota_to_sim.sim_limite(1) + "," #9
			texto << nota_fiscal.numero_da_nota.sim_limite(15) + "," #10
			texto << (self.try(:lote).present? ? self.lote.data_referencia : self.data_referencia).sim_data.first(6).to_s + "," #11
			texto << nota_fiscal.serie_do_selo.to_s.sim_limite(2) + "," #12
			texto << nota_fiscal.numero_do_selo.to_s.sim_limite(10) + "," #13
			texto << nota_fiscal.numero_da_serie_do_selo.to_s.sim_limite(10) + "," #14
			texto << nota_fiscal.numeros_de_formularios.to_s.sim_limite(255) + "," #15
			texto << (nota_fiscal.data_limite_de_expedicao.present? ? nota_fiscal.data_limite_de_expedicao.sim_data : nota_fiscal.data_de_emissao.sim_data) + "," #16
			texto << (incricao.present? ? incricao.to_s.sim_limite(16) : '""') + "," #17
			texto << nota_fiscal.liquidacao.pessoa.cidade.try(:estado).try(:codigo_uf).to_s.sim_limite(2) + "," #18
			texto << (nota_fiscal.data_de_emissao.present? ? nota_fiscal.data_de_emissao.sim_data : nota_fiscal.data_limite_de_expedicao.sim_data) + "," #19
			texto << val_liquuido_total.to_f.to_s.sim_valor + "," #20
			texto << (val_desconto_total != 0 ? val_desconto_total.to_f.to_s.sim_valor : "0.00") + "," #21
			texto << val_total_nfs.to_f.to_s.sim_valor + "," #22
			texto << (valor_descontos.to_f !=0  ? valor_descontos.to_f.to_s.sim_valor : "0.00") + "," #23
			texto << (base_calculo.to_f !=0  ? base_calculo.to_f.to_s.sim_valor : "0.00") + "," #24
			texto << nota_fiscal.read_attribute_before_type_cast(:tipo_de_emissao).to_s + "," #25
			texto << (nota_fiscal.read_attribute_before_type_cast(:tipo_de_emissao) == 1 ? nota_fiscal.numero_protocolo_de_autorizacao : "0") + "," #26
			texto << (nota_fiscal.chave_de_acesso.present? ? nota_fiscal.chave_de_acesso : '0') + "," #27
			texto << (nota_fiscal.chave_de_verificacao.present? ? nota_fiscal.chave_de_verificacao.to_s.sim_limite(50) : '""') + "," #28
			texto << nota_fiscal.liquidacao.empenho.try(:pessoa).try(:cpf_ou_cnpj_sem_pontos).sim_limite(14) #29

			return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, self.numero_da_nota, atributo_falho, coluna)
			else
				raise e
			end
		end
	end

end
