# frozen_string_literal: true

class DsnAuthenticationService
  class AuthenticationError < StandardError; end

  def self.authenticate(request)
    # Try multiple authentication methods in order of preference

    # Method 1: Query parameter authentication
    dsn_key = extract_key_from_query_params(request)
    return find_dsn(dsn_key) if dsn_key

    # Method 2: X-Baffle-Auth header (similar to X-Sentry-Auth)
    dsn_key = extract_key_from_baffle_auth_header(request)
    return find_dsn(dsn_key) if dsn_key

    # Method 3: Authorization Bearer token
    dsn_key = extract_key_from_authorization_header(request)
    return find_dsn(dsn_key) if dsn_key

    # Method 4: Basic auth (username is the dsn_key)
    dsn_key = extract_key_from_basic_auth(request)
    return find_dsn(dsn_key) if dsn_key

    raise AuthenticationError, "No valid authentication method found"
  end

  private

  def self.extract_key_from_query_params(request)
    # Support both baffle_key and sentry_key for compatibility
    request.GET['baffle_key'] || request.GET['sentry_key'] || request.GET['glitchtip_key']
  end

  def self.extract_key_from_baffle_auth_header(request)
    auth_header = request.headers['X-Baffle-Auth'] || request.headers['X-Sentry-Auth']
    return nil unless auth_header

    # Parse: Baffle baffle_key=dsn_key, baffle_version=1
    # Or: Sentry sentry_key=dsn_key, sentry_version=7
    match = auth_header.match(/(?:baffle_key|sentry_key)=([^,\s]+)/)
    match&.[](1)
  end

  def self.extract_key_from_authorization_header(request)
    authorization_header = request.headers['Authorization']
    return nil unless authorization_header

    # Parse: Bearer dsn_key
    if authorization_header.start_with?('Bearer ')
      authorization_header[7..-1].strip
    end
  end

  def self.extract_key_from_basic_auth(request)
    authorization_header = request.headers['Authorization']
    return nil unless authorization_header&.start_with?('Basic ')

    # Decode basic auth: username:password (password is ignored)
    credentials = Base64.decode64(authorization_header[6..-1])
    username = credentials.split(':').first
    username
  end

  def self.find_dsn(dsn_key)
    return nil unless dsn_key.present?

    # Find DSN by key
    dsn = Dsn.authenticate(dsn_key)
    raise AuthenticationError, "Invalid DSN key" unless dsn

    # Ensure DSN is enabled
    raise AuthenticationError, "DSN is disabled" unless dsn.enabled?

    dsn
  end
end
