// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

import { createSign } from 'node:crypto';

import OAuth from 'oauth-1.0a';

import type { AuthConfig, AuthStrategy, Credentials } from '../auth-strategy.js';
import { MissingCredentialsError } from '../errors.js';

function buildOauth(consumerKey: string, privateKey: string): OAuth {
  return new OAuth({
    consumer: { key: consumerKey, secret: privateKey },
    signature_method: 'RSA-SHA1',
    // oauth-1.0a's `getSigningKey()` always percent-encodes `consumer.secret`
    // before passing it here — correct for HMAC-SHA1 (a literal shared
    // secret) but not for RSA-SHA1, where the secret is a PEM private key:
    // percent-encoding mangles its spaces/newlines into `%20`/`%0A`, which
    // OpenSSL then fails to decode. Ignore the corrupted `key` argument and
    // sign with the real `privateKey` from the closure instead.
    hash_function(baseString: string) {
      return createSign('RSA-SHA1').update(baseString).sign(privateKey, 'base64');
    },
  });
}

export class OAuth1Strategy implements AuthStrategy {
  async authenticate(config: AuthConfig): Promise<Credentials> {
    const { consumerKey, privateKey, token } = config;
    if (!consumerKey || !privateKey) {
      throw new MissingCredentialsError(['consumerKey', 'privateKey']);
    }
    return { consumerKey, privateKey, ...(token ? { token } : {}) };
  }

  validateCredentials(credentials: Credentials): boolean {
    return typeof credentials.consumerKey === 'string' && typeof credentials.privateKey === 'string';
  }

  /**
   * Computes the per-request `Authorization` header. Unlike the other
   * strategies, OAuth1 signs the method + URL + params on every call, so
   * this can't be precomputed once in `authenticate()` — callers (the
   * generated API client, Story 12) call this immediately before dispatch.
   */
  buildAuthorizationHeader(credentials: Credentials, method: string, url: string): string {
    const oauth = buildOauth(credentials.consumerKey, credentials.privateKey);
    const token = credentials.token ? { key: credentials.token, secret: '' } : undefined;
    const authorized = oauth.authorize({ url, method }, token);
    return oauth.toHeader(authorized).Authorization;
  }
}
