/**
 * Generate a self-contained nats-server config string for auth-callout mode
 * (Stage A, PR1).
 *
 * Key points mirroring the spike caveat in decision 0007:
 * - We do NOT use the wrapper's websocket+config combination (causes include
 *   mis-resolution). This config is written to a temp file and passed via -c
 *   to the binary directly.
 * - The config includes the websocket{} block, JetStream, and the full
 *   accounts + authorization { auth_callout { … } } block.
 */

export interface CalloutConfigOptions {
  /** TCP listen port; -1 = nats-server picks a random one. */
  port?: number
  /** WebSocket listen port; -1 = nats-server picks a random one. */
  wsPort?: number
  /** Host to bind. Default: 127.0.0.1 */
  host?: string
  /** JetStream store directory. */
  storeDir?: string
  /**
   * Optional HTTP monitoring port (bound to 127.0.0.1 only). When set, enables
   * the nats-server monitoring endpoints (/connz, /subsz, /varz) for diagnostics.
   * Localhost-only — never exposed beyond the server host. Off when undefined.
   */
  monitorPort?: number
  /** Public key of the callout issuer account. */
  accountPublicKey: string
  /** Public key of the auth-service user (bypasses the callout). */
  authUserPublicKey: string
  /** Name used for the callout account and auth_users entry. */
  accountName?: string
}

/**
 * Return a complete nats-server configuration string for callout mode.
 * The config is self-contained (no `include` directives) so it can be written
 * to any path and passed to nats-server via `-c`.
 */
export function buildCalloutConfig(opts: CalloutConfigOptions): string {
  const host = opts.host ?? "127.0.0.1"
  const port = opts.port ?? -1
  const wsPort = opts.wsPort ?? -1
  const accountName = opts.accountName ?? "CALLOUT_ACCOUNT"

  const lines: string[] = [
    `# nats-server config — auth-callout mode (generated by Airaknit)`,
    `host: "${host}"`,
    `port: ${port}`,
    ``,
    // Raise the per-message ceiling from the 1 MB default to 8 MB so chat
    // snapshots (compressed) and composer file attachments (~5 MB raw → ~6.8 MB
    // base64) fit in a single request. Files larger than this need chunking
    // (see docs/stories/composer-file-attachments). Matches the assumption in
    // src/shared/compression.ts.
    `max_payload: 8388608`,
    ``,
    `# JetStream`,
    `jetstream: true`,
    ...(opts.storeDir ? [`store_dir: "${opts.storeDir}"`] : []),
    ``,
    // HTTP monitoring (diagnostics only, localhost-bound). Enables /connz, /subsz,
    // /varz so we can inspect connections + per-connection subscriptions. Off
    // unless monitorPort is provided.
    ...(opts.monitorPort ? [`http: "127.0.0.1:${opts.monitorPort}"`, ``] : []),
    `# WebSocket`,
    `websocket {`,
    `  host: "${host}"`,
    `  port: ${wsPort}`,
    `  no_tls: true`,
    `}`,
    ``,
    `# Accounts — one account holds all connections`,
    `accounts {`,
    `  ${accountName} {`,
    `    jetstream: enabled`,
    `    users [`,
    `      # auth_users: this user bypasses the callout (the responder itself)`,
    `      { nkey: "${opts.authUserPublicKey}" }`,
    `    ]`,
    `  }`,
    `}`,
    ``,
    `# Auth-callout — delegate authorization to the responder`,
    `authorization {`,
    `  auth_callout {`,
    `    issuer: "${opts.accountPublicKey}"`,
    `    auth_users: [ "${opts.authUserPublicKey}" ]`,
    `    account: "${accountName}"`,
    `  }`,
    `}`,
  ]

  return lines.join("\n") + "\n"
}

/**
 * Validate the generated config shape by checking for required sections.
 * Used in tests; not called in production code.
 */
export function validateCalloutConfigShape(config: string): {
  ok: boolean
  missing: string[]
} {
  const required = [
    "auth_callout",
    "issuer:",
    "auth_users:",
    "account:",
    "websocket",
    "jetstream",
  ]
  const missing = required.filter((s) => !config.includes(s))
  return { ok: missing.length === 0, missing }
}
