/**
 * RFC-020 §15.1 — feishu outbound/attachment path helpers (SHARED).
 *
 * Single source of truth for `/work/feishu-attachments/<conn>/<convKey>/`
 * naming. Used by:
 *
 *   - `adapter.ts` inbound `downloadImage` (subdir for received images),
 *   - `bridge.ts` outbound marker whitelist (where the agent may write),
 *   - `worker.ts` outbound envelope (the concrete path injected into the
 *     agent's prompt, so what we tell the agent matches what we accept).
 *
 * 2026-06-29 Vincent UAT: prior to this module, the inbound downloader
 * used `conversationId.replace(/[^a-zA-Z0-9_-]/g, "_")` and the outbound
 * bridge whitelist used `sender.id` for DMs / `chatId` for groups. The
 * two algorithms diverged — agent learned the inbound oc_<chat>/ layout
 * from incoming attachments, then wrote outbound files to the same
 * oc_<chat>/ subdir, but the bridge required ou_<userid>/. Every PDF
 * generated by the bot was rejected. This module unifies on
 * `conversationId` (the open_chat_id assigned by Feishu — present for
 * DMs and groups equally).
 */

/**
 * Sanitize a raw Feishu conversation id (`oc_<hex>` / occasionally
 * `om_<id>` for DMs) into a filesystem-safe segment. Identical to the
 * adapter.ts inbound download path policy — DO NOT CHANGE without also
 * migrating any on-disk attachments under the old key.
 *
 * The regex strips anything outside `[A-Za-z0-9_-]`, replacing with `_`.
 * Falsy / non-string input returns the empty string; caller is
 * responsible for substituting a fallback (the empty key would resolve
 * to `/work/feishu-attachments/<conn>//` which the path-prefix
 * whitelist rejects cleanly).
 */
export function feishuConvKey(rawId: string | undefined | null): string {
  if (!rawId || typeof rawId !== "string") return "";
  return rawId.replace(/[^a-zA-Z0-9_-]/g, "_");
}

/**
 * Compute the canonical per-conversation directory for outbound file
 * dispatch + inbound attachment downloads. Trailing slash included so
 * `.startsWith(...)` whitelist checks are unambiguous about the
 * conversation boundary (no `oc_abc` matching `oc_abc_x`).
 *
 * Example:
 *   feishuOutboundDir("feishu-local", "oc_9a7eedbba275a87999f7ee2cfb10f4cb")
 *   → "/work/feishu-attachments/feishu-local/oc_9a7eedbba275a87999f7ee2cfb10f4cb/"
 */
export function feishuOutboundDir(connectionName: string, rawConvId: string | undefined | null): string {
  const conn = connectionName || "feishu";
  const conv = feishuConvKey(rawConvId);
  return `/work/feishu-attachments/${conn}/${conv}/`;
}

/**
 * The fixed prefix root used as a sanity check by the marker validator.
 * Useful for tests + for `validateOutboundPath` defense-in-depth.
 */
export const OUTBOUND_ROOT = "/work/feishu-attachments";
