class Lutaml::Hal::Client

HAL Client for making HTTP requests to HAL APIs

def create_connection

def create_connection
  Faraday.new(url: @api_url) do |conn|
    conn.use Faraday::FollowRedirects::Middleware
    conn.request :json
    conn.response :json, content_type: /\bjson$/
    conn.adapter Faraday.default_adapter
  end
end

def debug_api_log(response, url)

def debug_api_log(response, url)
  if defined?(Rainbow)
    puts Rainbow("\n===== Lutaml::Hal DEBUG: HAL API REQUEST =====").blue
  else
    puts "\n===== Lutaml::Hal DEBUG: HAL API REQUEST ====="
  end
  puts "URL: #{url}"
  puts "Status: #{response.status}"
  # Format headers as JSON
  puts "\nHeaders:"
  headers_hash = response.headers.to_h
  puts JSON.pretty_generate(headers_hash)
  puts "\nResponse body:"
  if response.body.is_a?(Hash) || response.body.is_a?(Array)
    puts JSON.pretty_generate(response.body)
  else
    puts response.body.inspect
  end
  if defined?(Rainbow)
    puts Rainbow("===== END DEBUG OUTPUT =====\n").blue
  else
    puts "===== END DEBUG OUTPUT =====\n"
  end
end

def get(url, params = {})

Make a GET request to the API
def get(url, params = {})
  cache_key = "#{url}:#{params.to_json}"
  return @cache[cache_key] if @cache_enabled && @cache.key?(cache_key)
  @last_response = @connection.get(url, params)
  response = handle_response(@last_response, url)
  @cache[cache_key] = response if @cache_enabled
  response
rescue Faraday::ConnectionFailed => e
  raise ConnectionError, "Connection failed: #{e.message}"
rescue Faraday::TimeoutError => e
  raise TimeoutError, "Request timed out: #{e.message}"
rescue Faraday::ParsingError => e
  raise ParsingError, "Response parsing error: #{e.message}"
rescue Faraday::Adapter::Test::Stubs::NotFound => e
  raise LinkResolutionError, "Resource not found: #{e.message}"
end

def get_by_url(url, params = {})

Get a resource by its full URL
def get_by_url(url, params = {})
  # Strip API endpoint if it's included
  path = strip_api_url(url)
  get(path, params)
end

def handle_response(response, url)

def handle_response(response, url)
  debug_api_log(response, url) if @debug
  case response.status
  when 200..299
    response.body
  when 400
    raise BadRequestError, response_message(response)
  when 401
    raise UnauthorizedError, response_message(response)
  when 404
    raise NotFoundError, response_message(response)
  when 500..599
    raise ServerError, response_message(response)
  else
    raise Error, response_message(response)
  end
end

def initialize(options = {})

def initialize(options = {})
  @api_url = options[:api_url] || raise(ArgumentError, 'api_url is required')
  @connection = options[:connection] || create_connection
  @params_default = options[:params_default] || {}
  @debug = options[:debug] || !ENV['DEBUG_API'].nil?
  @cache = options[:cache] || {}
  @cache_enabled = options[:cache_enabled] || false
  @api_url = strip_api_url(@api_url)
end

def response_message(response)

def response_message(response)
  message = "Status: #{response.status}"
  message += ", Error: #{response.body['error']}" if response.body.is_a?(Hash) && response.body['error']
  message
end

def strip_api_url(url)

Strip any trailing slash from the API URL
def strip_api_url(url)
  url.sub(%r{/\Z}, '')
end