class Contabilidade::Diaria < ApplicationRecord
	include IncrementadorDeCodigoConcern

	has_paper_trail

	attr_default :viagem_exterior, false
	attr_default :dotacao_na_diaria, true

	belongs_to :orcamento, required: true
	belongs_to :unidade_orcamentaria, class_name: 'Loa::UnidadeOrcamentaria', required: true
	belongs_to :agente_publico_municipal, class_name: 'Base::AgentePublicoMunicipal', required: true
	belongs_to :cidade, class_name: 'Base::Cidade'
	belongs_to :arquivo, class_name: 'Tcm::Arquivo', required: false

	has_one :orcamento_da_despesa_por_diaria, class_name: 'Contabilidade::OrcamentoDaDespesaPorDiaria', dependent: :destroy
	has_one :empenho, dependent: :destroy
	has_one :passagem, class_name: 'Contabilidade::Passagem', dependent: :destroy

	has_many :documentos_da_diaria, class_name: 'Contabilidade::DocumentoDaDiaria', dependent: :destroy

	validates_presence_of :orcamento_id, :unidade_orcamentaria_id, :agente_publico_municipal_id, :data_da_portaria, :numero_da_portaria
	validates_presence_of :data_da_viagem, :data_do_retorno, :qtd_de_diarias, :valor, :historico
	validates_presence_of :viagem_exterior, if: Proc.new { cidade_id.blank? }
	validates_presence_of :local_exterior, if: Proc.new { viagem_exterior.present? }
	validates_presence_of :cidade_id, if: Proc.new { viagem_exterior.blank? }

	validates_uniqueness_of :numero, scope: :orcamento_id, case_sensitive: false

	validates_length_of :numero_da_portaria, maximum: 13

	validate :data_do_retorno_antes_da_data_da_viagem?, if: Proc.new { data_do_retorno && data_da_viagem }
	validate :data_da_diaria_apos_a_data_da_viagem?, if: Proc.new { data_da_portaria && data_da_viagem }

	validates :data_da_portaria, mesmo_exercicio_do_pai: true, if: Proc.new { data_da_portaria.present?}
	validates :data_da_portaria, date: true, if: Proc.new { data_da_portaria.present? }
	validates :data_da_viagem, date: true
	validates :data_do_retorno, date: true

	before_create :atribui_codigo_disponivel, if: Proc.new { |objeto| objeto.numero.nil? }
	before_update :atribui_codigo_disponivel, if: Proc.new { |objeto| objeto.data_da_portaria_changed? }

	def atribui_codigo_disponivel
		gerar_codigo(data_da_portaria, :numero, :data_da_portaria, :orcamento_id, self.orcamento_id)
	end

	def dotacao_inclusa?
		orcamento_da_despesa_por_diaria.present?
	end

	def valor_da_dotacao_igual_valor_da_diaria?
		dotacao_inclusa? && valor_total == orcamento_da_despesa_por_diaria.valor.to_d
	end

	def pode_empenhar?
		(!dotacao_na_diaria || (dotacao_na_diaria && valor_da_dotacao_igual_valor_da_diaria?)) && numero_da_portaria.present?
	end

	def empenho_gerado?
		empenho.present?
	end

	def data_do_retorno_antes_da_data_da_viagem?
		errors.add(:data_da_viagem, 'não pode ser após o retorno') if data_da_viagem > data_do_retorno
	end

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

	def data_da_diaria_apos_a_data_da_viagem?
		errors.add(:data_da_portaria, 'não pode ser após a data da viagem') if data_da_portaria > data_da_viagem
	end

	def valor_total
		(qtd_de_diarias * valor.to_f).round(2)
	end

	def codigo_e_descricao
		"#{numero} - #{agente_publico_municipal.nome}"
	end

	def portaria_agente_publico_e_empenho
		if empenho.present?
			"Portaria: #{numero_da_portaria} | Agente Público: #{agente_publico_municipal.nome} | Empenho: #{empenho.numero_do_empenho}"
		else
			"Portaria: #{numero_da_portaria} | Agente Público: #{agente_publico_municipal.nome}"
		end
	end

	def situacao_de_pagamento
		if empenho.present? && empenho.confirmado?
			if empenho.valor_total_liquidado != empenho.definir_valor_do_empenho
				"A Liquidar"
			elsif empenho.valor_total_liquidado == empenho.definir_valor_do_empenho && empenho.valor_liquidado_pago == 0.00
				"Liquidada"
			elsif empenho.valor_liquidado_pago == empenho.definir_valor_do_empenho
				"Pago"
			else
			"Pago Parcialmente"
			end
		else
			'A Empenhar'
		end
	end

	def esta_empenhada?
		empenho.present?
	end

	def to_sim(data_referencia)
		texto = ""
		#como só tem 1 empenho e esse empenho só pode te ruma liquidação, porém essa liquidação tem varios pagamentos, 
		#é necessario que pra cada pagamento seja gerado uma linha pra esse sim
		#essa regra vai precisar refeita quando for feito varios tipos de empenho
		begin
			data = (data_referencia + "01").to_date

			if self.empenho.orcamento.exercicio != data.year && self.empenho.empenho_de_restos_a_pagar.present?
				pagamentos = self.empenho.empenho_de_restos_a_pagar.liquidacoes.first.pagamentos
			else
				pagamentos = self.empenho.liquidacoes.first.pagamentos
			end

			pagamentos.each do |pagamento|
				texto << "805".to_s.sim_preenche(3) + "," #1
				texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," #2
				texto << orcamento.exercicio.to_s + "00" + "," #3
				texto << unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #4
				texto << unidade_orcamentaria.codigo.codigo_uo_to_sim + "," #5
				texto << agente_publico_municipal.cpf.to_s.sim_limite(11) + "," #6
				texto << numero_da_portaria.to_s.sim_limite(10) + "," #7
				texto << data_da_portaria.sim_data + "," #8
				texto << data_referencia.to_s + "," #9
				texto << historico.sim_descricao.sim_limite(255) + "," #10

				if viagem_exterior.present?
					codigo_cidade = local_exterior
					codigo_estado = 'EX'
				else
					codigo_cidade = cidade.nome
					codigo_estado = cidade.estado.uf
				end

				texto << codigo_cidade.to_s.sim_limite(40) + "," #11
				texto << codigo_estado.to_s.sim_limite(2) + "," #12
				texto << data_da_viagem.sim_data + ","#13
				texto << data_do_retorno.sim_data + ","#14
				texto << sprintf('%.1f', qtd_de_diarias).to_f.to_s + ","#15
				texto << valor.to_f.to_s.sim_valor + "," #16
				texto << valor_total.to_f.to_s.sim_valor + ","#17
				texto << empenho.data_do_empenho.sim_data + ","#18
				texto << empenho.numero_do_empenho.to_s.sim_limite(8) + ","#19

				if empenho.ordinario?
					codigo_sub_empenho = "000"
				else
					codigo_sub_empenho = "001"
				end

				texto << codigo_sub_empenho.sim_limite(3) + "," #20
				texto << pagamento.numero.to_s.sim_limite(8)#21
			end

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