/**
 * Sanity-check the `SESSION_SECRET` env var early in bootstrap so a
 * missing or obviously weak value fails fast instead of producing
 * weak cookie integrity at runtime.
 *
 * Wired in `main.ts` alongside `assertDatabaseUrl()` and
 * `assertEntraConfig()` — same family of pre-flight check per
 * ADR-0018 §"BFF env-var loading".
 *
 * `SESSION_SECRET` signs the transient pre-auth cookie (state + PKCE
 * verifier carried between `/auth/login` and `/auth/callback`, per
 * ADR-0009) and will later cover the session cookie's integrity
 * layer (per ADR-0010). One secret for the cookie family is enough;
 * payload encryption uses dedicated keys (`SESSION_ENCRYPTION_KEY`,
 * `OBO_CACHE_ENCRYPTION_KEY`) when those features land.
 */

const PLACEHOLDER = 'replace_with_32_random_bytes_base64url';
const MIN_ENTROPY_BYTES = 32;

export function assertSessionSecret(): string {
  const raw = process.env['SESSION_SECRET'];
  if (!raw || raw === '') {
    throw new Error(
      `SESSION_SECRET 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_SECRET is still set to the .env.example placeholder ` +
        `("${PLACEHOLDER}"). Replace with a real random value.`,
    );
  }

  // Decode base64url-ish input — accept base64 too (Node decodes
  // both). Anything below 32 bytes of decoded entropy is weaker than
  // the AES-256 key family the project uses elsewhere; reject early.
  let decoded: Buffer;
  try {
    decoded = Buffer.from(raw, 'base64url');
  } catch {
    throw new Error(`SESSION_SECRET must be a base64url-encoded string. Got: ${truncate(raw)}`);
  }

  if (decoded.length < MIN_ENTROPY_BYTES) {
    throw new Error(
      `SESSION_SECRET decodes to ${decoded.length} bytes, ` +
        `below the ${MIN_ENTROPY_BYTES}-byte minimum (≈ 256 bits of entropy). ` +
        `Generate a longer value.`,
    );
  }

  return raw;
}

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