/**
 * Sanity-check the `SESSION_ENCRYPTION_KEY` env var early in
 * bootstrap so a missing or obviously weak value fails fast instead
 * of producing weak at-rest encryption at runtime.
 *
 * Wired in `main.ts` alongside the other `assertX()` validators —
 * same pre-flight family per ADR-0018 §"BFF env-var loading".
 *
 * `SESSION_ENCRYPTION_KEY` is the AES-256-GCM key used by the
 * session middleware to encrypt the payload before `connect-redis`
 * writes it to Redis (per ADR-0010 §"At-rest encryption"). It is
 * **distinct** from `SESSION_SECRET`, which only signs the cookie's
 * session id — never reuse one for the other.
 *
 * Returns the decoded 32-byte key as a `Buffer` so callers can pass
 * it straight to `crypto.createCipheriv('aes-256-gcm', key, iv)`
 * without re-decoding per request.
 */

const PLACEHOLDER = 'replace_with_32_random_bytes_base64url';
const REQUIRED_KEY_BYTES = 32;

export function assertSessionEncryptionKey(): Buffer {
  const raw = process.env['SESSION_ENCRYPTION_KEY'];
  if (!raw || raw === '') {
    throw new Error(
      `SESSION_ENCRYPTION_KEY is not set. Generate one with ` +
        `"node -e \\"console.log(require('crypto').randomBytes(32).toString('base64url'))\\"" ` +
        `and put it in apps/portal-bff/.env.`,
    );
  }

  if (raw === PLACEHOLDER) {
    throw new Error(
      `SESSION_ENCRYPTION_KEY is still set to the .env.example placeholder ` +
        `("${PLACEHOLDER}"). Replace with a real random value.`,
    );
  }

  let decoded: Buffer;
  try {
    decoded = Buffer.from(raw, 'base64url');
  } catch {
    throw new Error(
      `SESSION_ENCRYPTION_KEY must be a base64url-encoded string. Got: ${truncate(raw)}`,
    );
  }

  // AES-256-GCM mandates a 32-byte key — anything else is rejected by
  // `crypto.createCipheriv` at first call. Catch the misconfiguration
  // at boot, not on the first authenticated request.
  if (decoded.length !== REQUIRED_KEY_BYTES) {
    throw new Error(
      `SESSION_ENCRYPTION_KEY decodes to ${decoded.length} bytes, ` +
        `but AES-256-GCM requires exactly ${REQUIRED_KEY_BYTES}. ` +
        `Generate a fresh value.`,
    );
  }

  return decoded;
}

function truncate(s: string): string {
  return s.length > 16 ? `${s.slice(0, 16)}…` : s;
}
