// Display-only prettifier for raw llama-swap model ids shown in the model
// pickers (BooChat ModelPicker + BooCode AgentComposerBar). The actual model id
// sent to the backend is never changed — this only affects what's rendered.
//
//   qwen3.6-35b-a3b-mxfp4          -> Qwen3.6 35B
//   qwopus3.5-9b-coder-mtp         -> Qwopus3.5 9B Coder
//   qwen3.5-9b-deepseek-v4-mtp     -> Qwen3.5 9B Deepseek
//   nemotron-cascade-2-30b-a3b     -> Nemotron Cascade 2 30B
//   negentropy-4.7-9b              -> Negentropy 4.7 9B
//   glm-4.7-flash                  -> GLM 4.7 Flash
//   north-mini-code                -> North Mini Code
//   gemma-3-270m                   -> Gemma 3 270M
//   OpenCode Zen/Big Pickle        -> Big Pickle
//   llama-swap/Qwen 3.6 27B MTP    -> Qwen 3.6 27B MTP
//
// OpenCode surfaces models as "Provider Group/Model Name"; we drop the group
// prefix and show just the model name. Ids that already contain whitespace are
// treated as friendly labels and returned unchanged.

// Quant / format / speculative-decoding tags that carry no meaning for a human
// scanning the picker. Dropped from the label.
const DROP_TOKENS = new Set([
  'mtp', 'mxfp4', 'fp4', 'fp8', 'fp16', 'bf16',
  'q4', 'q5', 'q6', 'q8', 'int4', 'int8',
  'awq', 'gptq', 'gguf',
]);

// Family/qualifier tokens that read better fully uppercased than title-cased.
const ACRONYMS = new Set(['glm', 'lfm', 'gpt', 'vl', 'oss', 'rnj', 'ibm']);

// Title-case a token, but uppercase its leading-letter run when it's a known
// acronym so "glm" -> "GLM" and "lfm2.5" -> "LFM2.5".
function titleToken(t: string): string {
  const m = /^([a-z]+)(.*)$/.exec(t);
  if (m && ACRONYMS.has(m[1])) return m[1].toUpperCase() + m[2];
  return t.charAt(0).toUpperCase() + t.slice(1);
}

export function formatModelLabel(raw: string): string {
  if (!raw) return raw;
  // OpenCode-style "Provider Group/Model Name" → keep just the model name.
  const slash = raw.lastIndexOf('/');
  if (slash >= 0) raw = raw.slice(slash + 1).trim();

  if (/\s/.test(raw)) return raw; // already a friendly (spaced) label

  const kept: string[] = [];
  raw.split('-').forEach((t, i) => {
    if (DROP_TOKENS.has(t)) return;       // quant / format / decoding tags
    if (/^v\d+$/.test(t)) return;         // version-variant tag: v1, v2, v4
    if (/^a\d+b$/.test(t)) return;        // MoE active-params tag: a3b
    if (i > 0 && /^\d+(\.\d+)?[bm]$/.test(t)) { kept.push(t.toUpperCase()); return; } // size: 9B, 27B, 270M
    kept.push(titleToken(t));             // family, version, descriptor
  });
  return kept.length ? kept.join(' ') : raw;
}
