class Contabilidade::Retencao < ApplicationRecord
	has_paper_trail
	include TradutorConcern
	include GeradorDeEventosContabeis

	attr_accessor :valor_da_liquidacao, :tipo_iss
	attr_default :base_de_calculo, Proc.new{ |retencao| retencao.pagamento.valor.to_f }
	attr_accessor :usar_orcamento_mais_recente
	attr_default :usar_orcamento_mais_recente, false
	attr_accessor :nao_faz_duplicada_de_rp
	attr_default :nao_faz_duplicada_de_rp, false

	belongs_to :nota_fiscal, inverse_of: :retencoes
	belongs_to :pagamento, inverse_of: :retencoes
	belongs_to :liquidacao
	belongs_to :imposto, polymorphic: true
	belongs_to :conta_extra_orcamentaria, class_name: 'Contabilidade::ContaExtraOrcamentaria'
	belongs_to :conta_bancaria, class_name: 'Base::ContaBancaria'
	belongs_to :arquivo, class_name: 'Tcm::Arquivo', required: false
	has_many :taloes_de_receita, class_name: "Contabilidade::TalaoDeReceita"

	has_one :pagamentos_das_retencoes, class_name: "Contabilidade::PagamentoDaRetencao", dependent: :destroy

	#before_create :set_valor_calculado, if: Proc.new{!conta_extra_orcamentaria.present? && !valor_calculado.present?}
	#before_update :set_valor_calculado, if: Proc.new{!conta_extra_orcamentaria.present?}
	before_update :deleta_taloes_de_receita , if: Proc.new { self.tipo_de_acao_changed?}

	after_save :cria_talao_de_receita_extra_pagamento, if: Proc.new { self.pagamento.present? && (self.pagar? || self.pagar_recolher? || self.reter? || self.transferir?) }

	after_save :atualiza_valor_do_talao, if: Proc.new { taloes_de_receita.any?}

	validates_presence_of :imposto_id, :imposto_type, :aliquota, if: Proc.new{!conta_extra_orcamentaria.present?}
	validates_presence_of :base_de_calculo
	validates_presence_of :tipo_de_acao, if: Proc.new{valor_calculado.present?}

	validates_numericality_of :aliquota, greater_than: 0, less_than_or_equal_to: 100, if: Proc.new{!conta_extra_orcamentaria.present?}
	validates_numericality_of :base_de_calculo, greater_than: 0, if: Proc.new{!conta_extra_orcamentaria.present?}
	validates_numericality_of :valor_calculado, greater_than: 0, if: Proc.new{conta_extra_orcamentaria.present?}

	validate :deve_reter_inss_pf_para_reter_irrf_pf, if: Proc.new{|retencao| retencao.pagamento.present? && retencao.imposto_type.present? && retencao.imposto_type.demodulize.downcase.include?('irrfpessoafisica')}
	validate :conta_extra_possui_unidade_orcamentaria, if: Proc.new{ conta_extra_orcamentaria_id.present? && imposto_id.present? }
	validate :valida_imposto_atividade, if: Proc.new{ self.liquidacao.present? && !liquidacao.tem_folha_de_pagamento? && !liquidacao.sem_nota? && !liquidacao.fatura? }
	validate :valor_calculado_nao_pode_ser_maior_que_base_de_calculo, if: Proc.new{ self.valor_calculado.present? && self.valor_calculado_changed? }

	before_validation :atribui_conta_extra_orcamentaria, if: Proc.new{ imposto_id.present? && (conta_extra_orcamentaria.nil? || imposto_id_changed?)  }
	after_save :apaga_a_si_mesmo_se_valor_calculado_igual_a_zero, if: Proc.new{conta_extra_orcamentaria.present?}
	after_destroy :deleta_taloes_de_receita

	after_create :cria_retencao_no_restos_a_pagar, if: Proc.new { self.existe_restos_a_pagar_na_origem? }
	before_save :lanca_as_mudancas_no_restos_a_pagar_se_tiver, if: Proc.new { self.existe_restos_a_pagar_na_origem? }

	before_update :atualiza_dependecias, if: Proc.new { self.conta_extra_orcamentaria_id_changed? || self.tipo_de_acao_changed? }

	accepts_nested_attributes_for :pagamentos_das_retencoes

	enum tipo_de_acao: {
		pagar: 0,
		pagar_recolher: 1,
		transferir: 2,
		reter: 4,
		nao_selecionar: 3
	}

	def existe_restos_a_pagar_na_origem?
		self.try(:liquidacao).try(:empenho).try(:empenho_de_restos_a_pagar).present? || self.try(:nota_fiscal).try(:liquidacao).try(:empenho).try(:empenho_de_restos_a_pagar).present?
	end

	def origem_de_restos_a_pagar?
		(self.try(:liquidacao).try(:restos_a_pagar?) && self.try(:liquidacao).try(:empenho).try(:empenho_origem).present?) || (self.try(:nota_fiscal).try(:liquidacao).try(:restos_a_pagar?) && self.try(:nota_fiscal).try(:liquidacao).try(:empenho).try(:empenho_origem).present?)
	end

	def numero_do_pagamento_da_retencao
		pagamentos_das_retencoes.try(:despesa_extra_orcamentaria).try(:numero_de_caixa)
	end

	def cria_talao_de_receita_extra_pagamento
		liquidacao_do_pagamento = pagamento.liquidacao
		conta_extra = define_contra_extra_do_talao_de_receita

		if liquidacao_do_pagamento.present? && (self.pagar_recolher? || self.transferir? || self.reter? || (self.pagar? && conta_extra.passivo?))
			unidade_liquidacao = liquidacao_do_pagamento.unidade_orcamentaria_do_exercicio_atual(orcamento)
			data_do_pagamento = pagamento.data
			pessoa = liquidacao_do_pagamento.credor

			valor_do_talao = valor_calculado.to_f
			historico_do_talao = define_historico_do_talao_baseado_na_liquidacao(liquidacao_do_pagamento, false)
			talao_existente = unidade_liquidacao.orgao.orcamento.taloes_de_receita.where(retencao_id: self.id )

			# unidade do exercicio correspodente pegando da liquidacao

			natureza_da_receita = self.conta_extra_orcamentaria_do_exercicio_atual.try(:natureza_da_receita)
			unidade_da_conta_extra = natureza_da_receita.unidades_orcamentarias_por_natureza_da_receita.where(unidade_orcamentaria_id: unidade_liquidacao.id).first rescue nil

			if natureza_da_receita.present? && unidade_da_conta_extra.present? && unidade_da_conta_extra.orcamentos_da_receita.sum(&:valor) > 0
				# se a conta tem receita e se a receita tem previsão orçamentária
				self.cria_talao_de_receita_orcamentario_pagamento
			else
				if !talao_existente.present? && conta_extra.present?

					conta_bancaria_por_unidade_orcamentaria_id = pagamento.contas_bancarias_por_pagamento.first.conta_bancaria.contas_bancarias_por_unidade_orcamentaria.where(unidade_orcamentaria_id: unidade_liquidacao.id).first

					talao_de_receita = Contabilidade::TalaoDeReceita.new(
						orcamento_id: contexto_atual.id,
						data_do_talao: data_do_pagamento,
						valor: valor_do_talao,
						conta_bancaria_por_unidade_orcamentaria_id: conta_bancaria_por_unidade_orcamentaria_id.id,
						historico: historico_do_talao,
						pessoa_id: pessoa.id,
						documento_de_credito: '0',
						tipo_de_documento: :outro_tipo_de_documento_de_credito,
						tipo_do_talao: :original,
						conta_extra_orcamentaria_id: conta_extra.id,
						origem_do_talao: :extra_orcamentario,
						unidade_orcamentaria_id: unidade_liquidacao.id,
						retencao_id: self.id,
						talao_de_desconto: true,
						pagamento_id: pagamento.id,
						lancamento_automatico_retencao: true
					)

					unless talao_de_receita.valid?
						talao_de_receita.errors.each do |key, value|
							self.errors.add(:base, "#{value.try(:capitalize)}")
						end
					end

					unless talao_de_receita.save
						raise talao_de_receita.errors.full_messages.join(', ')
					end
				end
			end
		end
	end

	def cria_talao_de_receita_orcamentario_pagamento
		liquidacao_do_pagamento = pagamento.liquidacao

		if liquidacao_do_pagamento.present?
			unidade_liquidacao = liquidacao_do_pagamento.unidade_orcamentaria_do_exercicio_atual(contexto_atual)
			data_do_pagamento = pagamento.data
			pessoa = liquidacao_do_pagamento.credor

			valor_do_talao = valor_calculado.to_f
			receita_talao = receita_extra_do_talao_de_receita
			conta_extra_orcamentaria_do_exercicio_atual.try(:natureza_da_receita)
			historico_do_talao = define_historico_do_talao_baseado_na_liquidacao(liquidacao_do_pagamento, true)
			talao_existente = orcamento.taloes_de_receita.where(retencao_id: self.id )
			conta_bancaria = self.pagamento.contas_bancarias.first.contas_bancarias_por_unidade_orcamentaria.find_by(unidade_orcamentaria_id: self.unidade_orcamentaria.id).id rescue nil

			if !talao_existente.present? && receita_talao.present?
				talao_de_receita = Contabilidade::TalaoDeReceita.new(
					orcamento_id: contexto_atual.id,
					data_do_talao: data_do_pagamento,
					valor: valor_do_talao,
					historico: historico_do_talao,
					pessoa_id: pessoa.id,
					documento_de_credito: '0',
					tipo_de_documento: :outro_tipo_de_documento_de_credito,
					natureza_da_receita_id: receita_talao.id,
					tipo_do_talao: :original,
					origem_do_talao: :orcamentario,
					unidade_orcamentaria_id: unidade_liquidacao.id,
					retencao_id: self.id,
					talao_de_desconto: true,
					skip_callback: true,
					pagamento_id: pagamento.id,
					conta_bancaria_por_unidade_orcamentaria_id: conta_bancaria
				)

				unidade_por_natureza_da_receita = Loa::UnidadeOrcamentariaPorNaturezaDaReceita.where(unidade_orcamentaria: unidade_liquidacao, natureza_da_receita: receita_talao).first
				orcamentos_da_receita = receita_extra_do_talao_de_receita.orcamentos_da_receita.where( unidade_orcamentaria_por_natureza_da_receita_id: unidade_por_natureza_da_receita.id).order(:fonte_de_recursos_id) rescue nil

				orcamentos_da_receita.each do |orcamento_da_receita|
					percentual_da_fonte = (orcamento_da_receita.valor / unidade_por_natureza_da_receita.valor_total)

					valor = (percentual_da_fonte * talao_de_receita.valor)

					if orcamento_da_receita == orcamentos_da_receita.last
						valor = talao_de_receita.valor - talao_de_receita.complementos_por_fonte_do_talao_de_receita.sum(&:valor)
					end

					complemento = talao_de_receita.complementos_por_fonte_do_talao_de_receita.build(
						orcamento_da_receita: orcamento_da_receita,
						valor: valor
					)
				end

				unless talao_de_receita.valid?
					talao_de_receita.errors.each do |key, value|
						self.errors.add(:base, "#{value.try(:capitalize)}")
					end
				end

				if talao_de_receita.save
					talao_de_receita.skip_callback = false
					talao_de_receita.gerar_todos_os_movimentos(:data_do_talao, orcamento)
				else
					raise talao_de_receita.errors.full_messages.join(', ')
				end
			end
		end
	end

	def define_historico_do_talao_baseado_na_liquidacao(liquidacao = self.liquidacao, historico_de_vies_orcamentario)
		categoria = historico_de_vies_orcamentario ? 'Receita' : 'Retenção'

		if self.pagamento.present?
			if self.conta_extra_orcamentaria.present?
				"Receita Extraorçamentária - #{categoria} #{self&.conta_extra_orcamentaria&.descricao}, decorrente do pagamento #{self&.pagamento&.numero}. Contribuinte #{self&.pagamento&.credor&.nome}. "
			else
				"Receita Orçamentária - #{categoria} #{self&.natureza_da_receita&.descricao}, decorrente do pagamento #{self&.pagamento&.numero}. Contribuinte #{self&.pagamento&.credor&.nome}. "
			end
		elsif liquidacao.tem_folha_de_pagamento?
			"Receita Orçamentária - #{categoria}, decorrente da liquidação #{liquidacao.empenho_e_numero} - Folha de Pagamento."
		elsif liquidacao.nota_fiscal_numero.present?
			"Receita Orçamentária - #{categoria}, decorrente da nota fiscal #{liquidacao.nota_fiscal_numero}, liquidação #{liquidacao.empenho_e_numero}."
		else
			"Receita Orçamentária - #{categoria}, decorrente da liquidação #{liquidacao.empenho_e_numero}"
		end
	end

	def define_contra_extra_do_talao_de_receita
		if conta_extra_orcamentaria.present?
			conta_extra_orcamentaria
		elsif imposto.present? && receita_extra_orcamentaria.present?
			contexto_atual.contas_extra_orcamentarias.find_by(natureza_da_receita_id: receita_extra_orcamentaria.id)
		end
	end

	def receita_extra_do_talao_de_receita
		if conta_extra_orcamentaria.present? && conta_extra_orcamentaria.natureza_da_receita.present?
			conta_extra_orcamentaria.natureza_da_receita
		elsif imposto.present? && receita_extra_orcamentaria.present?
			receita_extra_orcamentaria
		end
	end

	def atualiza_valor_do_talao
		valor_do_talao = valor_calculado.to_f
		talao_existente = contexto_atual.taloes_de_receita.find_by(retencao_id: self.id )

		if talao_existente.present?
			talao_existente.valor = valor_do_talao
			talao_existente.save
		end
	end

	def receita_extra_orcamentaria
		case imposto_type
		when "Contabilidade::IrrfPessoaJuridica"
			contexto_atual.contas_extra_orcamentarias.find_by(retencao_para: 5).try(:natureza_da_receita)
		when "Contabilidade::ImpostoSobreServico"
			contexto_atual.contas_extra_orcamentarias.find_by(retencao_para: 1).try(:natureza_da_receita)
		when "Contabilidade::IrrfPessoaFisica"
			contexto_atual.contas_extra_orcamentarias.find_by(retencao_para: 4).try(:natureza_da_receita)
		when "Contabilidade::InssPessoaFisica"
			contexto_atual.contas_extra_orcamentarias.find_by(retencao_para: 2).try(:natureza_da_receita)
		when "Contabilidade::InssPessoaJuridica"
			contexto_atual.contas_extra_orcamentarias.find_by(retencao_para: 2).try(:natureza_da_receita)
		end
	end

	def natureza_da_receita_possui_vinculo_com_unidade?
		receita_extra_orcamentaria.unidades_orcamentarias_por_natureza_da_receita.where(unidade_orcamentaria_id: get_liquidacao.unidade_orcamentaria_do_exercicio_atual(orcamento).id).any? rescue false
	end

	def descricao_imposto
		if imposto_type == "Contabilidade::IrrfPessoaJuridica"
			"IRRF - Pessoa Jurídica"
		elsif imposto_type == "Contabilidade::ImpostoSobreServico"
			"ISS"
		elsif imposto_type == "Contabilidade::IrrfPessoaFisica"
			"IRRF - Pessoa Física"
		elsif imposto_type == "Contabilidade::InssPessoaFisica"
			"INSS - Pessoa Física"
		elsif imposto_type == "Contabilidade::InssPessoaJuridica"
			"INSS - Pessoa Jurídica"
		else
			""
		end
	end

	def classificacao_da_receita
		classe_do_imposto = self.imposto.class.model_name rescue ""
		if classe_do_imposto == "Contabilidade::ImpostoSobreServico"
			if orcamentario_iss?
				"Orçamentário"
			else
				"Extraorçamentário"
			end

		elsif classe_do_imposto == "Contabilidade::InssPessoaJuridica"
			if orcamentario_inss_pj?
				"Orçamentário"
			else
				"Extraorçamentário"
			end

		elsif classe_do_imposto == "Contabilidade::IrrfPessoaJuridica"
			if orcamentario_irpj?
				"Orçamentário"
			else
				"Extraorçamentário"
			end

		elsif classe_do_imposto == "Contabilidade::IrrfPessoaFisica"
			if orcamentario_irpf?
				"Orçamentário"
			else
				"Extraorçamentário"
			end
		else
			if extraorcamentario_inss_pf?
				"Extraorçamentário"
			else
				'Orçamentário'
			end
		end
	end

	def classificacao_da_receita_abreviada
		classe_do_imposto = imposto.class.model_name rescue ""
		case classe_do_imposto
		when "Contabilidade::ImpostoSobreServico"
			carater_abreviado(orcamentario_iss?)
		when "Contabilidade::InssPessoaJuridica"
			carater_abreviado(orcamentario_inss_pj?)
		when "Contabilidade::IrrfPessoaJuridica"
			carater_abreviado(orcamentario_irpj?)
		when "Contabilidade::IrrfPessoaFisica"
			carater_abreviado(orcamentario_irpf?)
		else
			carater_abreviado(orcamentario_inss_pf?)
		end
	end

	def carater_abreviado(orcamentaria)
		orcamentaria ? "Orçam" : "Extraorç"
	end

	def orcamentario?
		orcamentario_iss? || orcamentario_inss_pj? || orcamentario_inss_pj? || orcamentario_irpj? || orcamentario_inss_pf?
	end

	def classe_do_imposto_abreviada
		classe_do_imposto = imposto.class.model_name rescue ""
		case classe_do_imposto
		when "Contabilidade::ImpostoSobreServico"
			"ISS"
		when "Contabilidade::InssPessoaJuridica"
			"INSS-PJ"
		when "Contabilidade::IrrfPessoaJuridica"
			"IR-PJ"
		when "Contabilidade::IrrfPessoaFisica"
			"IR-PF"
		else
			"INSS-PF"
		end
	end

	def orcamentario_iss?
		nota_fiscal.try(:orcamentario_iss) || pagamento.try(:orcamentario_iss)
	end

	def orcamentario_inss_pj?
		nota_fiscal.try(:orcamentario_inss_pj) || pagamento.try(:orcamentario_inss_pj)
	end

	def orcamentario_irpj?
		nota_fiscal.try(:orcamentario_irpj) || pagamento.try(:orcamentario_irpj)
	end

	def orcamentario_irpf?
		nota_fiscal.try(:orcamentario_irpf) || pagamento.try(:orcamentario_irpf)
	end

	def orcamentario_inss_pf?
		!extraorcamentario_inss_pf?
	end

	def extraorcamentario_inss_pf?
		nota_fiscal.try(:extraorcamentario_inss_pf) || pagamento.try(:extraorcamentario_inss_pf)
	end

	def enviado_ao_sim?
		arquivo_id.present? && arquivo_id > 0 && arquivo.lote.lote_processado_ou_enviado?
	end

	def to_sim(data_referencia, args)
		# Variáveis necessárias para gerar o SIM
		# Apenas as retenções de Pagamento é que vão para o SIM
		begin
			exercicio_do_orcamento = args[:pagamento].orcamento.exercicio.to_s
			unidade_orcamentaria = args[:pagamento].unidade_orcamentaria_atual
			orgao = unidade_orcamentaria.orgao
			empenho = args[:pagamento].liquidacao.empenho
			liquidacao = args[:pagamento].liquidacao

			if self.classificacao_da_receita == "Extraorçamentário"
				classificacao_deducao = "E"
			else
				classificacao_deducao = "O"
			end

			texto = ""
			texto << "609".sim_preenche(3) + "," #1
			texto << Configuracao.first.codigo_do_municipio_no_tcm.sim_preenche(3) + "," #2
			texto << "#{empenho.orcamento.exercicio}00" + "," #3
			texto << orgao.codigo.sim_preenche(2) + "," #4
			texto << unidade_orcamentaria.codigo.codigo_uo_to_sim + "," #5
			texto << empenho.data_do_empenho.sim_data + "," #6
			texto << empenho.numero_do_empenho.to_s.sim_limite(8) + "," #7
			texto << (liquidacao.empenho.ordinario? ? '"000"' : '"001"') + "," #8
			texto << pagamento.numero.sim_limite(8) + "," #9
			texto << args[:conta_extra_orcamentaria].to_s + "," #10
			texto << data_referencia.to_s + "," #11
			texto << args[:total].to_f.to_s.sim_valor + "," #12
			texto << classificacao_deducao.sim_limite(1) #13

			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, "", atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def deleta_taloes_de_receita
		if taloes_de_receita.any?
			taloes_de_receita.each do |talao_existente|
				talao_existente.destroy
			end
		end
	end

	def codigo_e_descricao_imposto
		"#{self.imposto.codigo} - #{self.imposto.class.model_name.human.to_s}"
	end

	def valor_pago
		@valor_pago ||= pagamentos_das_retencoes.sum(:valor)
	end

	def valor_a_pagar
		@valor_a_pagar ||= (valor_calculado || base_de_calculo) - valor_pago
	end

	def valor_pagamento_com_desconto
		pagamento.valor - valor_calculado
	end

	def descricao_da_acao
		if self.pagar?
			'Ação PAGAR: Lançamento da despesa extra orçamentária na Unidade Gestora do Empenho para o credor associado a conta extra. Conta Origem Obrigatória'
		elsif self.pagar_recolher?
			'Ação Pagar/Recolher: Lançamento da despesa extra orçamentária na Unidade Gestora do Empenho para o credor associado a Unidade Gestora da conta destino. Lançamento de Receita Extra Orçamentária ou Receita Orçamentária para a Unidade Gestora da conta destino tendo como contribuinte a pessoa associada a unidade gestora do empenho.Contas Origem e Destino obrigatórias.'
		elsif self.transferir?
			'Ação Transferir: Opção de transferir o valor da retenção para outra conta corrente da unidade gestora do empenho. Ação opcional do usuário.'
		end
	end

	def descricao_pagamento
		"PAGAMENTO: #{self.pagamento&.numero} - CONTRA EXTRA.: #{self.conta_extra_orcamentaria&.codigo_completo_e_descricao} - VALOR: #{self.valor_calculado.try(:real_contabil)}"
	end

	def valida_imposto_atividade
		errors.add(:imposto_id, "O campo precisa ser preenchido") if !self.imposto_id.present?
	end

	def atribui_conta_extra_orcamentaria
		self.conta_extra_orcamentaria_id = self.conta_extra_orcamentaria_do_exercicio_atual.try(:id)
	end

	def conta_extra_orcamentaria_do_exercicio_atual
		# atualiza com a funcao orcamento
		if imposto_type.eql?("Contabilidade::ImpostoSobreServico")
			Contabilidade::ContaExtraOrcamentaria.find_by(orcamento_id: orcamento.id, descricao: 'ISS')
		elsif imposto_type.eql?("Contabilidade::IrrfPessoaFisica") || imposto_type.eql?("Contabilidade::IrrfPessoaJuridica")
			Contabilidade::ContaExtraOrcamentaria.find_by(orcamento_id: orcamento.id, descricao: 'IRRF Outros Rendimentos *')
		elsif imposto_type.eql?("Contabilidade::InssPessoaFisica") || imposto_type.eql?("Contabilidade::InssPessoaJuridica")
			Contabilidade::ContaExtraOrcamentaria.find_by(orcamento_id: orcamento.id, descricao: 'INSS Terceiros')
		else
			contexto_atual.contas_extra_orcamentarias.where(codigo: self.conta_extra_orcamentaria.codigo).first
		end
	end

	def orcamento
		if usar_orcamento_mais_recente == true
			Orcamento.order("exercicio asc").last
		else
			contexto_atual
		end
	end

	def unidade_orcamentaria
		@unidade_orcamentaria ||=
			if pagamento.present?
				pagamento.liquidacao.unidade_orcamentaria_do_exercicio_atual(orcamento)
			elsif liquidacao.present?
				liquidacao.unidade_orcamentaria_do_exercicio_atual(orcamento)
			elsif nota_fiscal.present?
				nota_fiscal.liquidacao.unidade_orcamentaria_do_exercicio_atual(orcamento)
			end
	end

	def conta_destino
		conta_bancaria || pagamentos_das_retencoes.try(:conta_destino)
	end


	def conta_extra_possui_unidade_orcamentaria
		if get_liquidacao.restos_a_pagar?
			unidades_orcamentarias_de_todos_os_anos_ids = unidade_orcamentaria.unidade_gestora.unidades_orcamentarias.pluck(:id)
		else
			unidades_orcamentarias_de_todos_os_anos_ids = []
			unidades_orcamentarias_de_todos_os_anos_ids << unidade_orcamentaria.id
		end

		if conta_extra_orcamentaria.contas_extra_por_unidades_orcamentarias.find_by("unidade_orcamentaria_id in (?)", unidades_orcamentarias_de_todos_os_anos_ids).nil?
			errors.add(:conta_extra_orcamentaria_id, "Não possui conta para a unidade orçamentária #{unidade_orcamentaria.codigo_e_nome}" )
		end
	end

	def valor_calculado_nao_pode_ser_maior_que_base_de_calculo
		if self.imposto.present? && base_de_calculo.to_d < valor_calculado.to_d
			errors.add(:valor_calculado, "O valor do imposto não pode ser superior ao valor da base de calculo")
		end
	end

	def get_liquidacao
		return liquidacao if liquidacao.present?

		pagamento.try(:liquidacao) || nota_fiscal.try(:liquidacao)
	end

	def empenho
		get_liquidacao.empenho
	end

	def origem_da_retencao
		if liquidacao.present? || nota_fiscal.present?
			'liquidacao'
		elsif pagamento.present?
			'pagamento'
		end
	end

	def atributo_data
		if liquidacao.present?
			liquidacao.data_da_liquidacao
		elsif nota_fiscal.present?
			nota_fiscal.data_de_emissao
		elsif pagamento.present?
			pagamento.data
		end
	end

	def atributo_codigo
		if liquidacao.present?
			liquidacao.numero
		elsif nota_fiscal.present?
			nota_fiscal.liquidacao.numero
		elsif pagamento.present?
			pagamento.numero
		end
	end

	def cria_retencao_no_restos_a_pagar
		unless nao_faz_duplicada_de_rp == true
			if self.liquidacao.present?
				origem_de_rp = self.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.liquidacao.numero).first rescue nil

				if origem_de_rp.present?
					retencao = self.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.liquidacao.numero).first.retencoes_folha.where(conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id).first rescue nil

					if origem_de_rp.present? && retencao.nil?
						retencao = origem_de_rp.retencoes_folha.create(pagamento_id: self.pagamento_id, imposto_id: self.imposto_id, imposto_type: self.imposto_type, aliquota: self.aliquota,
							base_de_calculo: self.base_de_calculo, valor_calculado: self.valor_calculado, conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id,
							conta_bancaria_id: self.conta_bancaria_id, arquivo_id: self.arquivo_id, tipo_de_acao: self.tipo_de_acao, nao_faz_duplicada_de_rp: true)
					end
				end
			elsif nota_fiscal.present?
				origem_de_rp = self.nota_fiscal.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.nota_fiscal.liquidacao.numero).first rescue nil

				if origem_de_rp.present?
					unless origem_de_rp.nota_fiscal.present?
						origem_de_rp.nota_fiscal_tipo = self.nota_fiscal.liquidacao.nota_fiscal_tipo
						origem_de_rp.nota_fiscal_numero = self.nota_fiscal.liquidacao.nota_fiscal_numero
						origem_de_rp.save(validate: false)

						nota = self.nota_fiscal.dup
						nota.liquidacao_id = origem_de_rp.id
						nota.save(validate: false)
					end

					if origem_de_rp.nota_fiscal.present?
						retencao = self.nota_fiscal.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.nota_fiscal.liquidacao.numero).first.nota_fiscal.retencoes.where(imposto_id: self.imposto_id, imposto_type: self.imposto_type).first rescue nil

						if retencao.nil?
							retencao = origem_de_rp.nota_fiscal.retencoes.create(pagamento_id: self.pagamento_id, imposto_id: self.imposto_id, imposto_type: self.imposto_type, aliquota: self.aliquota,
								base_de_calculo: self.base_de_calculo, valor_calculado: self.valor_calculado, conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id,
								conta_bancaria_id: self.conta_bancaria_id, arquivo_id: self.arquivo_id, tipo_de_acao: self.tipo_de_acao, nao_faz_duplicada_de_rp: true)
						end
					end
				end
			end
		end
	end

	def lanca_as_mudancas_no_restos_a_pagar_se_tiver
		campos_alterados = self.changed

		if campos_alterados.size > 0
			if self.liquidacao.present?
				origem_de_rp = self.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.liquidacao.numero).first rescue nil

				if origem_de_rp.present?
					retencao = self.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.liquidacao.numero).first.retencoes_folha.where(conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id).first
					if retencao.present?
						campos_alterados.each do |campo|
							unless campo == 'liquidacao_id'
								retencao.update_column(campo, self["#{campo}".to_sym])
							end
						end
					end
				end
			elsif nota_fiscal.present?
				origem_de_rp = self.nota_fiscal.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.nota_fiscal.liquidacao.numero).first.nota_fiscal rescue nil

				if origem_de_rp.present?
					retencao = self.nota_fiscal.liquidacao.empenho.empenho_de_restos_a_pagar.liquidacoes.where(numero: self.nota_fiscal.liquidacao.numero).first.nota_fiscal.retencoes.where(imposto_id: self.imposto_id, imposto_type: self.imposto_type).first

					if retencao.present?
						campos_alterados.each do |campo|
							unless campo == 'nota_fiscal_id'
								retencao.update_column(campo, self["#{campo}".to_sym])
							end
						end
					end
				end
			end
		end
	end

	def retencao_no_pagamento
		Contabilidade::Retencao.where(valor_calculado: self.valor_calculado, conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id, pagamento_id: [self.liquidacao.pagamentos.confirmados_ou_superior.pluck(:id)]).first
	end

	def realizado?
		self.retencao_no_pagamento&.taloes_de_receita&.where("coalesce(valor_anulado, 0) = 0")&.any?
	end

	private
	def set_valor_calculado
		self.valor_calculado = (base_de_calculo.to_f * aliquota.to_f)/100.0 if !liquidacao.try(:tem_folha_de_pagamento?)
	end

	def atualiza_dependecias
		unless self.realizado?
			ret = Contabilidade::Retencao.where(valor_calculado: self.valor_calculado, conta_extra_orcamentaria_id: self.conta_extra_orcamentaria_id_was, pagamento_id: [self.liquidacao.pagamentos.confirmados_ou_superior.pluck(:id)]).first
			if ret.present?
				ret.update_column(:tipo_de_acao, self.tipo_de_acao) if self.tipo_de_acao_changed?
				ret.update_column(:conta_extra_orcamentaria_id, self.conta_extra_orcamentaria_id) if self.conta_extra_orcamentaria_id_changed?
			end
		end
	end

	def apaga_a_si_mesmo_se_valor_calculado_igual_a_zero
		self.delete unless self.valor_calculado.to_f > 0
	end

	def deve_reter_inss_pf_para_reter_irrf_pf
		if !pagamento.retem_inss_pf? && !(pagamento.decorrente_de.eql?('Aluguel') || pagamento.isento_de_inss || pagamento.liquidacao.nota_fiscal_tipo == 'aluguel')
			errors.add(:imposto_id, 'deve calcular primeiro o INSS para poder calcular o IRRF')
		end
	end
end
