# frozen_string_literal: true

class Acme::Client::Resources::Directory
  DIRECTORY_RESOURCES = {
    new_nonce: 'newNonce',
    new_account: 'newAccount',
    new_order: 'newOrder',
    new_authz: 'newAuthz',
    revoke_certificate: 'revokeCert',
    key_change: 'keyChange'
  }

  DIRECTORY_META = {
    terms_of_service: 'termsOfService',
    website: 'website',
    caa_identities: 'caaIdentities',
    external_account_required: 'externalAccountRequired'
  }

  def initialize(url, connection_options)
    @url, @connection_options = url, connection_options
  end

  def endpoint_for(key)
    directory.fetch(key) do |missing_key|
      raise Acme::Client::Error::UnsupportedOperation,
        "Directory at #{@url} does not include `#{missing_key}`"
    end
  end

  def terms_of_service
    meta[DIRECTORY_META[:terms_of_service]]
  end

  def website
    meta[DIRECTORY_META[:website]]
  end

  def caa_identities
    meta[DIRECTORY_META[:caa_identities]]
  end

  def external_account_required
    meta[DIRECTORY_META[:external_account_required]]
  end

  def meta
    directory[:meta]
  end

  private

  def directory
    @directory ||= load_directory
  end

  def load_directory
    body = fetch_directory
    result = {}
    result[:meta] = body.delete('meta')
    DIRECTORY_RESOURCES.each do |key, entry|
      result[key] = URI(body[entry]) if body[entry]
    end
    result
  rescue JSON::ParserError => exception
    raise Acme::Client::Error::InvalidDirectory,
      "Invalid directory url\n#{@directory} did not return a valid directory\n#{exception.inspect}"
  end

  def fetch_directory
    connection = Faraday.new(url: @directory, **@connection_options)
    connection.headers[:user_agent] = Acme::Client::USER_AGENT
    response = connection.get(@url)
    JSON.parse(response.body)
  end
end
