import { createHash, randomBytes } from 'node:crypto';

/**
 * PKCE helper functions for the Authorization Code flow (RFC 7636).
 *
 * These are pure functions — no side effects, no DI — so they can be tested
 * independently of the NestJS container.
 *
 * The algorithm for the S256 challenge (from o-auth-verify-pkce-s256.ts on the hub):
 *   code_challenge = BASE64URL(SHA256(code_verifier))
 *
 * Both functions are intentionally minimal: the complexity lives in the math, not
 * in the wiring. Keep them as pure utilities; the controller owns the orchestration.
 */

/**
 * Generates a cryptographically-random, URL-safe `code_verifier` per RFC 7636 §4.1.
 *
 * The RFC requires the verifier to be composed of unreserved characters
 * (A-Z / a-z / 0-9 / "-" / "." / "_" / "~") with a minimum length of 43.
 *
 * Implementation: 32 random bytes → base64url encoding → 43 characters of the
 * unreserved set. `base64url` is already URL-safe (replaces + with - and / with _,
 * drops padding = signs), so no further transformation is needed.
 */
export function generatePkceVerifier(): string {
  // 32 bytes → 43 base64url characters (256 bits of entropy).
  // RFC 7636 §4.1 defines a verifier LENGTH range of 43–128 characters; 43 chars satisfies
  // the minimum exactly.
  return randomBytes(32).toString('base64url');
}

/**
 * Computes the S256 `code_challenge` from a `code_verifier`.
 *
 * Algorithm: BASE64URL(SHA256(ASCII(code_verifier)))
 *
 * The result is what the BFF sends to the hub's `/authorize` endpoint and what the
 * hub verifies at the `/token` exchange (see `o-auth-verify-pkce-s256.ts`).
 */
export function generatePkceChallenge(codeVerifier: string): string {
  return createHash('sha256').update(codeVerifier).digest('base64url');
}
