require 'active_support/concern'

module IncrementadorDeCodigoConcern extend ActiveSupport::Concern
	def gerar_codigo data_da_acao, atributo_recebe_codigo, atributo_da_data, atributo_de_unicidade_do_codigo, valor_do_atributo_de_unidade, veio_da_transferencia_de_orcamento_do_pedido = false
		if data_da_acao.present?
			if veio_da_transferencia_de_orcamento_do_pedido
				pesquisa = self.class.where(
					'extract(day from data_do_pedido) = ? AND extract(month from data_do_pedido) = ? AND extract(year from data_do_pedido) in (?)', data_da_acao.day, data_da_acao.month, [data_da_acao.year, data_da_acao.year + 1]
				).where(atributo_de_unicidade_do_codigo.to_sym => valor_do_atributo_de_unidade)
			else
				pesquisa = self.class.where(
					atributo_da_data.to_sym => data_da_acao, atributo_de_unicidade_do_codigo.to_sym => valor_do_atributo_de_unidade
				)
			end
			codigos_utilizados = pesquisa.where.not(
				id: self.id
			).order(
				atributo_recebe_codigo.to_sym
			).pluck(
				atributo_recebe_codigo.to_sym
			).map{ |codigo|
				if codigo.to_s.length == 8
					if codigo.to_s[0..3] == (data_da_acao.day.digitos(2) + data_da_acao.month.digitos(2))
						codigo.to_s[4..7]
					end
				else
					codigo_aux = "0" + codigo.to_s[0..2]
					if codigo_aux == (data_da_acao.day.digitos(2) + data_da_acao.month.digitos(2))
						codigo.to_s[3..6]
					end
				end
			}
			if codigos_utilizados.compact.empty?
				self.send("#{atributo_recebe_codigo}=","#{data_da_acao.day.digitos(2)}#{data_da_acao.month.digitos(2)}0001")
			else
				codigos_disponiveis = (1..codigos_utilizados.compact.sort.last.to_i + 1).to_a - codigos_utilizados.compact.map(&:to_i)
				self.send("#{atributo_recebe_codigo}=", "#{data_da_acao.day.digitos(2)}#{data_da_acao.month.digitos(2)}#{codigos_disponiveis.first.digitos(4)}")
			end
		end
	end

	def gerar_sugestao_codigo atributo_do_codigo, tamanho_do_codigo, params_de_unicidade_do_codigo, somar_a_partir_do_primeiro_utilizado = false, valor_minimo = 1
		codigos_utilizados = self.class.where(
			params_de_unicidade_do_codigo
		).where.not(
			{ atributo_do_codigo => ['AA', 'AAA'] }
		).order(
			Arel.sql( atributo_do_codigo.to_s + '::integer')
		).pluck(
			atributo_do_codigo.to_sym
		).map { |codigo|
			codigo.to_i
		}
		if codigos_utilizados.any?
			if somar_a_partir_do_primeiro_utilizado
				codigos_disponiveis = ((codigos_utilizados.first.to_i)..(codigos_utilizados.last.to_i + 1)).to_a - codigos_utilizados
			else
				codigos_disponiveis = (1..codigos_utilizados.last.to_i + 1).to_a - codigos_utilizados
			end
			self.send( "#{atributo_do_codigo}=", codigos_disponiveis.first.digitos(tamanho_do_codigo) )
		else
			if valor_minimo == 1
				self.send( "#{atributo_do_codigo}=", 1.digitos(tamanho_do_codigo) )
			else
				self.send( "#{atributo_do_codigo}=", valor_minimo.digitos(tamanho_do_codigo) )
			end
		end
	end
end
