class Loa::Orgao < ApplicationRecord
	include IncrementadorDeCodigoConcern

	has_paper_trail

	after_initialize :sugestao_de_codigo, if: :new_record?

	attr_accessor :importado_do_orcamento_anterior

	before_save :upcase_sigla

	belongs_to :orcamento, required: true
	belongs_to :tipo_de_unidade_administrativa, class_name: 'Base::TipoDeUnidadeAdministrativa', required: true

	after_create :importar_unidades_orcamentarias_do_ppa, if: Proc.new{ |orgao| orgao.orgao_id.present? && !importado_do_orcamento_anterior }

	has_many :unidades_orcamentarias, dependent: :restrict_with_exception
	has_many :assessores_de_contabilidade_responsaveis

	validates_presence_of :orcamento_id, :codigo, :tipo_de_unidade_administrativa_id, :nome, :sigla,
		:cnpj, :endereco, :cep, :telefone, :email, :horario_inicio_funcionamento,
		:horario_fim_funcionamento, :status_do_orcamento

	validates_uniqueness_of :codigo, :nome, :sigla, scope: :orcamento_id

	validates_length_of :telefone, :fax, minimum: 10, allow_blank: true
	validates_length_of :cep, is: 8, allow_blank: true
	validates_length_of :cnpj, is: 14
	validates_length_of :codigo, maximum: 3
	validates_length_of :nome, maximum: 80
	validates_length_of :sigla, maximum: 10
	validates_length_of :endereco, maximum: 255
	validates_length_of :email, maximum: 50

	validates_cnpj :cnpj, :on => [:update, :create]

	validates_format_of :email,:with => /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/, allow_blank: true
	validates_format_of :horario_inicio_funcionamento,:horario_fim_funcionamento, with: /\A([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]\z/, allow_blank: true

	validate :horario_de_fim_maior_que_o_de_inicio
	validate :ambos_os_horarios_devem_ser_preenchidos
	validate :uniqueness_orgao_reserva_de_contingencia

	enum status_do_orcamento: STATUS_DO_ORCAMENTO

	scope :por_tipo_de_sistema, -> {
		if Configuracao.try(:first).try(:camara_municipal?)
			self.joins(:tipo_de_unidade_administrativa).where("base_tipos_de_unidades_administrativas.codigo = '02'")
		else
			self.joins(:tipo_de_unidade_administrativa).where("base_tipos_de_unidades_administrativas.codigo != '02'")
		end
	}

	def codigo_e_nome
		"#{codigo_com_zeros} - #{nome}"
	end

	def codigo_com_zeros
		self.codigo.to_i.try(:digitos, 2)
	end

	def nome_e_cnpj
		"#{self.try(:nome)} " + '(' + "#{self.try(:cnpj_com_pontos)}" + ')'
	end

	def to_sim
		begin
			numero_do_fax = fax.nil? ? "85000000000" : fax.to_s.sim_preenche(11)

			texto = ""
			texto << "103".to_s.sim_preenche(3) + ","
			texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," # criar campo na tabela de configuração
			texto << orcamento.exercicio.to_s.sim_limite_sem_aspas(4, "00") + ","
			texto << codigo.to_s.sim_preenche(2) + ","
			texto << tipo_de_unidade_administrativa.codigo.to_s.sim_preenche(2) + ","
			texto << nome.to_s.sim_limite(80) + ","
			texto << cnpj.to_s.sim_preenche(14) + ","
			texto << endereco.to_s.gsub(/["\r\n]/, "").sim_limite(255) + ","
			texto << cep.to_s.sim_limite(8) + ","
			texto << telefone.to_s.sim_preenche(11) + ","
			texto << numero_do_fax + ","
			texto << email.to_s.sim_limite(50)
			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.codigo, atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def cnpj_com_pontos
		if cnpj.present? && cnpj.size == 14
			"#{cnpj[0..1]}.#{cnpj[2..4]}.#{cnpj[5..7]}/#{cnpj[8..11]}-#{cnpj[12..13]}"
		else
			cnpj
		end
	end

	def importar_dados_do_orgao
		ppa_orgao = Ppa::Orgao.find(self.orgao_id)
		if ppa_orgao
			self.codigo = ppa_orgao.codigo_com_zeros
			self.nome = ppa_orgao.nome
			self.sigla = ppa_orgao.sigla
		end
	end

	def importar_unidades_orcamentarias_do_ppa
		ppa_orgao = Ppa::Orgao.find(self.orgao_id.to_i)
		if ppa_orgao.present?
			ppa_orgao.unidades_orcamentarias.each do |unidade_orcamentaria|
				Loa::UnidadeOrcamentaria.new({
						orgao_id: self.id,
						ppa_unidade_orcamentaria_id: unidade_orcamentaria.id,
						codigo: unidade_orcamentaria.codigo,
						nome: unidade_orcamentaria.nome,
						sigla: unidade_orcamentaria.sigla
					}).save(validate: false)
			end
		end
	end

	def valor_fixado_da_despesa
		self.unidades_orcamentarias.flat_map{|unidade| unidade.subacoes.flat_map{|subacao| subacao.valor_total_fixado_da_despesa.to_d}}.sum
	end

	def porcentagem_sobre_a_despesa_fixada_total
		valor_dos_orgaos_do_orcamento = valor_fixado_da_despesa_total_nos_orgaos
		return ((self.valor_fixado_da_despesa / valor_dos_orgaos_do_orcamento)*100).to_f.round(2)
	end

	def valor_fixado_da_despesa_total_nos_orgaos
		self.orcamento.orgaos.map(&:valor_fixado_da_despesa).sum
	end

	private
	def uniqueness_orgao_reserva_de_contingencia
		if self.try(:tipo_de_unidade_administrativa).try(:codigo) == '99'
			orgao_cadastrado = ::Loa::Orgao.find_by( orcamento_id: orcamento.id, tipo_de_unidade_administrativa_id: tipo_de_unidade_administrativa.id)
			errors.add(:tipo_de_unidade_administrativa_id, "já existe um orgão de reserva de contingência") if orgao_cadastrado.present?
		end
	end

	def sugestao_de_codigo
		gerar_sugestao_codigo( :codigo, 2, {orcamento_id: orcamento.id} ) if (orcamento.present? && codigo.blank?)
	end

	def upcase_sigla
		self.sigla.try(:upcase!)
	end

	def horario_de_fim_maior_que_o_de_inicio
		if horario_inicio_funcionamento.present? && horario_fim_funcionamento.present? &&
			((Time.parse(self.try(:horario_inicio_funcionamento)).hour > Time.parse(self.try(:horario_fim_funcionamento)).hour) ||
				((Time.parse(self.try(:horario_inicio_funcionamento)).hour == Time.parse(self.try(:horario_fim_funcionamento)).hour) &&
					Time.parse(self.try(:horario_inicio_funcionamento)).min > Time.parse(self.try(:horario_fim_funcionamento)).min))
			errors.add(:horario_fim_funcionamento, "horário de fim não pode ser menor que o de início")
		end
	end

	def ambos_os_horarios_devem_ser_preenchidos
		if horario_inicio_funcionamento.present? & horario_fim_funcionamento.blank?
			errors.add(:horario_fim_funcionamento, "tanto o início quanto o fim devem ser especificados")
		end
		if horario_fim_funcionamento.present? & horario_inicio_funcionamento.blank?
			errors.add(:horario_inicio_funcionamento, "tanto o início quanto o fim devem ser especificados")
		end
	end

end
