module OwlsValueGuide
	include HTTParty

	ITEMDATA_URL_TEMPLATE = Addressable::Template.new(
		"https://neo-owls.net/itemdata/{item_name}"
	)

	def self.find_by_name(item_name)
		# Load the itemdata, pulling from the Rails cache if possible.
		cache_key = "OwlsValueGuide/itemdata/#{item_name}"
		data = Rails.cache.fetch(cache_key, expires_in: 1.day) do
			load_itemdata(item_name)
		end

		if data == :not_found
			raise NotFound
		end

		# Owls has records of some items that it explicitly marks as having no
		# listed value. We don't care about that distinction, just return nil!
		return nil if data['owls_value'].blank?

		Value.new(data['owls_value'], parse_last_updated(data['last_updated']))
	end

	Value = Struct.new(:value_text, :updated_at)

	class Error < StandardError;end
	class NetworkError < Error;end
	class NotFound < Error;end

	private

	def self.load_itemdata(item_name)
		Rails.logger.info "[OwlsValueGuide] Loading value for #{item_name.inspect}"

		url = ITEMDATA_URL_TEMPLATE.expand(item_name: item_name)
		begin
			res = get(url, headers: {
				"User-Agent" => Rails.configuration.user_agent_for_neopets,
			})
		rescue StandardError => error
			raise NetworkError, "Couldn't connect to Owls: #{error.message}"
		end

		if res.code == 404
			# Instead of raising immediately, return `:not_found` to save this
			# result in the cache, then raise *after* we exit the cache block. That
			# way, we won't make repeat requests for items we have that Owls
			# doesn't.
			return :not_found
		end

		if res.code != 200
			raise NetworkError, "Owls returned status code #{res.code} (expected 200)"
		end

		begin
			res.parsed_response
		rescue HTTParty::Error => error
			raise NetworkError, "Owls returned unsupported data format: #{error.message}"
		end
	end

	def self.parse_last_updated(date_str)
		return nil if date_str.blank?

		begin
			Date.strptime(date_str, '%Y-%m-%d')
		rescue Date::Error
			Rails.logger.error(
				"[OwlsValueGuide] unexpected last_updated format: #{date_str.inspect}"
			)
			return nil
		end
	end
end