// src/components/keywords/planning/semantic-labels.ts — pure FR label mapping
// for `SemanticAnalysisSection` : job phases (fetch/extract/score/persist),
// coverage flags (`Coverage.flags` + the synthetic `mixed_intent` the section
// derives from `Intent.mixedIntent`, see `src/lib/semantic/types.ts`),
// archetypes (EN keys → FR, `StructureProfile.archetypes`), and intent mode
// (`Intent.mode`). No I/O, no React — testable in isolation.

export type SemanticJobPhase = "fetch" | "extract" | "score" | "persist";

const PHASE_LABELS: Record<SemanticJobPhase, string> = {
  fetch: "Récupération des pages",
  extract: "Extraction sémantique",
  score: "Calcul du score",
  persist: "Enregistrement",
};

/** Unknown phases (future runner phases, or a stale/renamed value) fall back
 *  to the raw string rather than throwing — the polling UI stays readable. */
export function phaseLabel(phase: string): string {
  return PHASE_LABELS[phase as SemanticJobPhase] ?? phase;
}

const ARCHETYPE_LABELS: Record<string, string> = {
  transactional: "transactionnel",
  editorial: "éditorial",
  unknown: "indéterminé",
};

export function archetypeLabel(archetype: string): string {
  return ARCHETYPE_LABELS[archetype] ?? archetype;
}

const INTENT_MODE_LABELS: Record<"inferred" | "manual", string> = {
  inferred: "inférée",
  manual: "manuelle",
};

export function intentModeLabel(mode: "inferred" | "manual"): string {
  return INTENT_MODE_LABELS[mode] ?? mode;
}

const LANG_MISMATCH_RE = /^lang_mismatch:(\d+)$/;
const JS_RENDERED_SUSPECTED_RE = /^js_rendered_suspected:(\d+)$/;
const JS_RENDERED_RE = /^js_rendered:(\d+)$/;
const THIN_CONTENT_SUSPECTED_RE = /^thin_content_suspected:(\d+)$/;

/**
 * Maps a coverage flag to a readable FR sentence. `empty_corpus`,
 * `lang_mismatch:<position>`, `js_rendered_suspected:<position>` and
 * `js_rendered:<position>` come straight from `Coverage.flags` (the latter
 * two added by `analysis-runner.ts` — `js_rendered_suspected` is a thin-HTML
 * page excluded from the aggregation, T1 fiabilité serp-semantics;
 * `js_rendered` is the S7 headless-render fallback recovering it into the
 * corpus instead, plan S7 Task 2); `mixed_intent` is a synthetic flag the
 * section adds from `Intent.mixedIntent` so all surface through one shared
 * mapping. Unknown flags fall back to the raw string.
 */
export function flagLabel(flag: string): string {
  if (flag === "empty_corpus") return "Corpus vide (aucune page exploitable)";
  if (flag === "mixed_intent")
    return "Intention mixte (pas de dominante claire)";
  const langMismatch = LANG_MISMATCH_RE.exec(flag);
  if (langMismatch) return `Langue différente en position ${langMismatch[1]}`;
  const jsRenderedSuspected = JS_RENDERED_SUSPECTED_RE.exec(flag);
  if (jsRenderedSuspected)
    return `Rendu JS suspecté en position ${jsRenderedSuspected[1]} (page exclue)`;
  const jsRendered = JS_RENDERED_RE.exec(flag);
  if (jsRendered) return `Rendu JS récupéré en position ${jsRendered[1]}`;
  const thinContent = THIN_CONTENT_SUSPECTED_RE.exec(flag);
  if (thinContent)
    return `Contenu trop pauvre en position ${thinContent[1]} (page exclue)`;
  return flag;
}
