require 'bearcat'

# Bearcat RSpec Helpers
# Can be included in your spec_helper.rb file by using:
# - `require 'bearcat/spec_helpers'`
# And
# - `config.include Bearcat::SpecHelpers`
module Bearcat::SpecHelpers
  SOURCE_REGEX = /(?<method>get|post|delete|put)\((?<quote>\\?('|"))(?<url>.*)\k<quote>/

  # Helper method to Stub Bearcat requests.
  # Automagically parses the Bearcat method source to determine the correct URL to stub.
  # Accepts optional keyword parameters to interpolate specific values into the URL.
  # Returns a mostly-normal Webmock stub (:to_return has been overridden to allow :body to be set to a Hash)
  def stub_bearcat(endpoint, prefix: nil, **kwargs)
    if prefix == true
      prefix = canvas_api_client if defined? canvas_api_client
      prefix = canvas_sync_client if defined? canvas_sync_client
    end
    prefix = case prefix
    when nil
      ''
    when false
      ''
    when true
      raise "stub_bearcat() prefix: set to true, but neither canvas_(sync|api)_client are defined"
    when Bearcat::Client
      prefix.prefix
    when String
      prefix
    end

    ruby_method = Bearcat::Client.instance_method(endpoint)
    match = SOURCE_REGEX.match(ruby_method.source)
    url = match[:url]
    url = url.gsub(/#\{(?<key>.*?)\}/) do |match|
      match = Regexp.last_match
      v = kwargs[match[:key].to_sym]
      case v
      when nil
        '\\w+'
      when Regexp
        v.source
      when String
        Regexp.escape(v)
      end
    end
    url = prefix + url if prefix.present?
    url_pattern = Regexp.new(url)
    stub = stub_request(match[:method].to_sym, url_pattern)
    stub.define_singleton_method(:to_return, ->(*resps) {
      resps.map do |resp|
        resp[:headers] ||= {}
        resp[:headers]["Content-Type"] ||= "application/json"
        resp[:body] = resp[:body].to_json
      end
      super(*resps)
    })
    stub
  end
end