class Contabilidade::SituacaoDaObra < ApplicationRecord
	include TradutorConcern
	include AASM
	include GeradorDeEventosContabeis
	include SimConcern

	has_paper_trail

	belongs_to :obra
	belongs_to :engenheiro_da_obra

	validates_presence_of :obra_id
	validates_presence_of :engenheiro_da_obra_id, unless: Proc.new{ self.nao_iniciada?}
	validates_presence_of :tipo_de_status_da_obra
	validates_presence_of :data_da_situacao

	validates_presence_of :data_do_termo_de_conclusao, if: Proc.new { tipo_de_status_da_obra.present? && (self.concluida_provisoria? || self.concluida_definitiva?) }
	validates_presence_of :tipo_de_termo, if: Proc.new { tipo_de_status_da_obra.present? && (self.concluida_provisoria? || self.concluida_definitiva?) }

	validates_presence_of :observacoes

	validates_length_of :tombo_do_bem, maximum: 20

	validate :nao_deve_preencher_o_termo_de_conclusao_se_nao_for_concluida
	validate :tipo_de_termo_deve_ser_de_acordo_com_a_conclusao
	validate :data_nao_pode_ser_anterior_a_data_de_inicio_da_obra
	validate :data_do_termo_de_conclusao_nao_pode_ser_anterior_a_data_de_situacao
	validate :data_da_situacao_deve_maior_ou_igual_a_ultima_situacao
	validate :data_da_situacao_deve_respeitar_periodo_do_envio_ao_sim, if: Proc.new { obra.enviado_ao_sim? }
	validate :tipo_de_status_nao_pode_ser_igual_a_situacao_atual
	validate :tipo_de_status_nao_pode_ser_alterado_para_nao_iniciado_apos_inicio, if: Proc.new { self.nao_iniciada? }
	validate :valida_tombo_do_terreno_ao_concluir, if: Proc.new { tipo_de_status_da_obra.present? && self.concluida_definitiva? }

	validates :data_da_situacao, date: true
	validates :data_do_termo_de_conclusao, date: { allow_blank: true }

	before_validation :set_engenheiro_responsavel

	after_create :apagar_movimentacoes_de_plano_de_contas_repetidas, if: Proc.new { self.tombada?}

	enum tipo_de_termo: {
		permanente: 0,
		provisorio: 1
	}

	enum tipo_de_status_da_obra: {
		nao_iniciada: 1,
		em_andamento: 2,
		paralisada: 3,
		concluida_provisoria: 4,
		concluida_definitiva: 5,
		tombada: 6
	}

	scope :iniciadas_e_nao_concluidas, -> {
		where(tipo_de_status_da_obra: [
			Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["em_andamento"],
			Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["paralisada"],
			Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["concluida_provisoria"]
		])
	}
	scope :paralisadas, -> {where(tipo_de_status_da_obra: [Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["paralisada"]])}
	scope :concluidas, -> {where(tipo_de_status_da_obra: [Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["concluida_definitiva"]])}
	scope :nao_iniciadas, -> {where(tipo_de_status_da_obra: [Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["nao_iniciada"]])}

	ransacker :situacao do
		Arel.sql("( SELECT situacoes_da_obra.tipo_de_status_da_obra
								FROM contabilidade_situacoes_da_obra as situacoes_da_obra
								WHERE situacoes_da_obra.obra_id = contabilidade_obras.id
								AND situacoes_da_obra.id =
									(
										SELECT MAX(max_situacoes.id)
										FROM contabilidade_situacoes_da_obra AS max_situacoes
										WHERE max_situacoes.obra_id = contabilidade_obras.id
									)
							)")
	end

	def set_engenheiro_responsavel
		engenheiro_da_obra = obra.engenheiro_responsavel if obra.present?
		self.engenheiro_da_obra_id = engenheiro_da_obra.id if engenheiro_da_obra.present?
	end

	def nao_deve_preencher_o_termo_de_conclusao_se_nao_for_concluida
		unless tipo_de_status_da_obra.present? && (self.concluida_provisoria? || self.concluida_definitiva?)
			errors.add(:data_do_termo_de_conclusao, 'não deve ser preenchido para esse tipo de situação') if data_do_termo_de_conclusao.present?
			errors.add(:tombo_do_bem, 'não deve ser preenchido para esse tipo de situação') if tombo_do_bem.present?
			errors.add(:tipo_de_termo, 'não deve ser preenchido para esse tipo de situação') if tipo_de_termo.present?
		end
	end

	def tipo_de_termo_deve_ser_de_acordo_com_a_conclusao
		if self.concluida_provisoria?
			errors.add(:tipo_de_termo, 'deve ser Provisório para esse tipo de situação') if tipo_de_termo.present? && self.permanente?
		elsif self.concluida_definitiva?
			errors.add(:tipo_de_termo, 'deve ser Permanente para esse tipo de situação') if tipo_de_termo.present? && self.provisorio?
		end
	end

	def data_nao_pode_ser_anterior_a_data_de_inicio_da_obra
		if obra.present? && !data_da_situacao.nil?
			errors.add(:data_da_situacao, "deve ser a partir do inicio da obra #{obra.data_de_inicio}") if data_da_situacao < obra.data_de_inicio
		end
	end

	def data_do_termo_de_conclusao_nao_pode_ser_anterior_a_data_de_situacao
		if obra.present? && data_da_situacao && !data_do_termo_de_conclusao.nil?
			errors.add(:data_do_termo_de_conclusao, "deve ser a partir da data da situação #{self.data_da_situacao}") if data_da_situacao > data_do_termo_de_conclusao
		end
	end

	def data_da_situacao_deve_maior_ou_igual_a_ultima_situacao
		if obra.present? && data_da_situacao
			ultima_situacao = obra.situacoes_da_obra.last
			errors.add(:data_da_situacao, "deve ser maior ou igual a data da última situação #{ultima_situacao.data_da_situacao}") if ultima_situacao.present? && data_da_situacao < ultima_situacao.data_da_situacao
		end
	end

	def data_da_situacao_deve_respeitar_periodo_do_envio_ao_sim
		if obra.present? && data_da_situacao
			errors.add(:data_da_situacao, "O SIM do mês já foi enviado.") if lote_do_sim_gerado?(data_da_situacao)
		end
	end

	def tipo_de_status_nao_pode_ser_igual_a_situacao_atual
		if id.nil? && obra.present? && obra.situacao_atual.present? && obra.situacao_atual.tipo_de_status_da_obra == self.tipo_de_status_da_obra && obra.situacao_atual.data_da_situacao.strftime('%Y-%m') == self.data_da_situacao.strftime('%Y-%m')
			errors.add(:tipo_de_status_da_obra, "já é a situação atual no mês")
		end
	end

	def tipo_de_status_nao_pode_ser_alterado_para_nao_iniciado_apos_inicio
		if id.nil? && obra.present? && obra.situacao_atual.present?
			tipo_de_status_nao_iniciado = Contabilidade::SituacaoDaObra.tipos_de_status_da_obra[:nao_iniciada]
			iniciado = Contabilidade::SituacaoDaObra.where("tipo_de_status_da_obra <> ? and obra_id = ?", tipo_de_status_nao_iniciado, obra.id).all.count > 0 ? true : false
			if tipo_de_status_da_obra.present? && tipo_de_status_nao_iniciado.present?
				errors.add(:tipo_de_status_da_obra, "obra já iniciada não pode ser alterado para não iniciado") if iniciado and tipo_de_status_da_obra == Contabilidade::SituacaoDaObra.where(tipo_de_status_da_obra: Contabilidade::SituacaoDaObra.tipos_de_status_da_obra[:nao_iniciada]).first.tipo_de_status_da_obra
			end
		end
	end

	def valida_tombo_do_terreno_ao_concluir
		if obra.tombo_do_terreno.blank?
			errors.add(:tipo_de_status_da_obra, 'antes de concluir preencha o campo Tombo do Terreno no cadastro de Obra/Serviço')
		end
	end

	def valida_engenheiro_responsavel_cadastrado
		raise "É necessário cadastrar engenheiro(a) responsável ao Status da Obra (status: #{tipo_de_status_da_obra_i18n} - id da Obra: #{self.obra.id.to_s} - Número da Obra: #{self.obra.codigo}.#{self.obra.data_de_inicio.year.to_s.last(2)} - tipo: #{self.obra.tipo_de_obra_i18n})" if engenheiro_da_obra.try(:pessoa).nil?
		
		raise "É necessário cadastrar o CPF do engenheiro(a) responsável vinculado ao Status da Obra(id: #{engenheiro_da_obra.try(:pessoa).try(:id)} - nome: #{engenheiro_da_obra.try(:pessoa).try(:nome)}" if engenheiro_da_obra.try(:pessoa).present? && engenheiro_da_obra.try(:pessoa).try(:cpf).nil?
	end

	def valida_tombo_de_obra_concluida
		if (self.concluida_definitiva? || self.concluida_provisoria?)
			raise "#{self.obra.tipo_de_obra_i18n} Nº: #{self.obra.codigo}.#{self.obra.data_de_inicio.year.to_s.last(2)} possui status de concluída, mas está sem o tombo do bem. Dever ser informado o tombo do bem." unless  self.try(:tombo_do_bem).present?
		end
	end

	def apagar_movimentacoes_de_plano_de_contas_repetidas
		if self.movimentacoes_do_plano_de_contas.any?
			movimentacoes_diferentes = self.movimentacoes_do_plano_de_contas.pluck(:conta_por_evento_contabil_id, :gerador_id).uniq
			movimentacoes_diferentes.each do |movimentacao|
				todas_movimentacoes = self.movimentacoes_do_plano_de_contas.where(conta_por_evento_contabil_id: movimentacao[0], gerador_id: movimentacao[1])
				if todas_movimentacoes.size > 1
					todas_movimentacoes.last.destroy
				end
			end
			#self.movimentacoes_do_plano_de_contas.destroy_all
		end
	end

	def tempo_transcorrido
		if obra.situacoes_da_obra.any?
			situacao_posterior = obra.situacoes_da_obra.where('contabilidade_situacoes_da_obra.created_at > ?', self.created_at).order(:id).first
			data_da_situacao_posterior = situacao_posterior.present? ? situacao_posterior.data_da_situacao : Date.today
			(data_da_situacao_posterior - self.data_da_situacao).to_whole
		end
	end

	def to_sim
		begin
			unidade_orcamentaria = obra.contrato.unidade_orcamentaria_do_exercicio
			exercicio_do_orcamento = unidade_orcamentaria.orgao.orcamento.exercicio.to_s
			observacoes_da_situacao = observacoes.present? ? observacoes : tipo_de_status_da_obra_i18n
			
			texto = ""
			texto << "903".to_s.sim_preenche(3) + "," #1
			texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," #2
			texto << obra.data_de_inicio.sim_data + "," #3
			texto << obra.tipo_para_o_sim.sim_limite(1)+ "," #4
			texto << obra.codigo.sim_preenche(4) + "," #5
			texto << data_da_situacao.sim_data + "," #6
			texto << ((self.concluida_provisoria? || self.concluida_definitiva?) ? "4".to_s.sim_limite(1) : self.read_attribute_before_type_cast(:tipo_de_status_da_obra).to_s.sim_limite(1)) + "," #7
			texto << engenheiro_da_obra.try(:pessoa).try(:cpf).to_s.sim_limite(11) + "," #8
			texto << engenheiro_da_obra.try(:pessoa).try(:nome).to_s.sim_limite(40) + "," #9
			texto << engenheiro_da_obra.try(:pessoa).try(:telefone).to_s.sim_limite(11) + "," #10
			texto << engenheiro_da_obra.try(:pessoa).try(:email).to_s.sim_limite(30) + "," #11
			texto << observacoes_da_situacao.to_s.sim_limite(255) + "," #12
	
			if self.concluida_definitiva?
				texto << data_do_termo_de_conclusao.sim_data + "," #13
				texto << self.read_attribute_before_type_cast(:tipo_de_termo).to_s.sim_limite(1) + "," #14
			else
				texto << '0' + "," #13
				texto << '0' + "," #14
			end
			
			texto << self.try(:tombo_do_bem).to_s.sim_limite(20) #15
	
			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
end
