/**
 * Fahrzeug-Code-/Allrad-Namensregel (geteiltes Modul).
 *
 * EIGENTUM: Admin-Workstream (Phase 4) ist der fachliche Eigentümer dieser
 * Datei. Der Such-Workstream IMPORTIERT `expandNameQuery` von hier (Plan WS5,
 * "Allrad-Logik: Import aus @/lib/admin/codes"), implementiert die Regel also
 * NICHT doppelt. Diese Datei ist bewusst rein (keine DB-/IO-Abhängigkeit),
 * damit sie ohne laufendes Postgres testbar ist.
 *
 * Allrad-Namensregel (NÖ LFV, siehe docs/reference/fahrzeug-katalog-noelfv.md):
 * Bei der Allradausführung wird das "A" IN die Abkürzung eingeschoben — also
 * "HLFA 3" statt "HLF 3 A". Die Allradform bezeichnet DIESELBE Vorlage; die
 * Suche behandelt "HLF 3" und "HLFA 3" gleich. Allrad bleibt zusätzlich über
 * das Merkmal `Allradantrieb = Ja` filterbar. Beispiele:
 *   "HLFA 3"   -> nameLikes: ["HLFA 3", "HLF 3"],   allradImpliziert: true
 *   "HLFA 1 W" -> nameLikes: ["HLFA 1 W", "HLF 1 W"], allradImpliziert: true
 *   "MTFA"     -> nameLikes: ["MTFA", "MTF"],        allradImpliziert: true
 *   "HLF 3"    -> nameLikes: ["HLF 3"],              allradImpliziert: false
 */

export interface ExpandedNameQuery {
  /** Alle Namensvarianten, nach denen (OR-verknüpft, case-insensitiv) gesucht wird. */
  nameLikes: string[];
  /** true, wenn der Eingabetext die Allradausführung (eingeschobenes "A") impliziert. */
  allradImpliziert: boolean;
}

/**
 * Erkennt das in eine Fahrzeug-Abkürzung eingeschobene "A" (Allrad) und liefert
 * sowohl die Originalschreibweise als auch die Grundform ohne "A". Die Heuristik
 * arbeitet auf dem ERSTEN Token (der Abkürzung) und lässt den Rest (z. B. " 1 W",
 * " 3", " 2000") unverändert.
 *
 * Erkennungsregel: Ein Großbuchstaben-Token, das auf "FA" endet und dessen
 * Grundform (das "A" am Ende entfernt) auf "F" endet (HLF/MTF/TLF/RLF/KLF/...).
 * Damit greift die Regel für HLFA/MTFA/TLFA/RLFA/KLFA/GTLFA usw., nicht aber
 * für Tokens, die ohnehin auf "FA" enden müssten ohne Allradbezug.
 */
export function expandNameQuery(raw: string): ExpandedNameQuery {
  const trimmed = raw.trim();
  if (trimmed === "") return { nameLikes: [], allradImpliziert: false };

  // Normalisiere Mehrfach-Leerzeichen für den Vergleich, behalte aber die
  // Eingabe als erste (exakte) Variante bei.
  const normalized = trimmed.replace(/\s+/g, " ");
  const spaceIdx = normalized.indexOf(" ");
  const abk = spaceIdx === -1 ? normalized : normalized.slice(0, spaceIdx);
  const rest = spaceIdx === -1 ? "" : normalized.slice(spaceIdx); // inkl. führendem Leerzeichen

  const grundform = entferneAllradInfix(abk);
  if (grundform === null) {
    return { nameLikes: [normalized], allradImpliziert: false };
  }

  const grundVariante = grundform + rest;
  // Original zuerst, dann Grundform; Duplikate vermeiden.
  const nameLikes =
    grundVariante === normalized ? [normalized] : [normalized, grundVariante];
  return { nameLikes, allradImpliziert: true };
}

/**
 * Liefert die Grundform einer Allrad-Abkürzung (entfernt das eingeschobene "A")
 * oder `null`, wenn das Token keine erkennbare Allradausführung ist.
 *
 * "HLFA" -> "HLF", "MTFA" -> "MTF", "TLFA" -> "TLF", "RLFA" -> "RLF".
 * "HLF" -> null (kein "A"), "MTF" -> null, "VF" -> null.
 */
function entferneAllradInfix(abk: string): string | null {
  // Token muss aus Großbuchstaben (ggf. mit Bindestrich) bestehen.
  if (!/^[A-ZÄÖÜ-]+$/.test(abk)) return null;
  if (!abk.endsWith("FA")) return null;
  const grund = abk.slice(0, -1); // entfernt das End-"A" -> endet auf "F"
  if (!grund.endsWith("F")) return null;
  // Grundform muss eine echte Fahrzeugabkürzung sein (≥2 Zeichen, endet auf F).
  if (grund.length < 2) return null;
  return grund;
}

/**
 * Hängt das Allrad-"A" IN die Abkürzung (an das erste Token), sofern noch nicht
 * vorhanden. "HLF 3" -> "HLFA 3", "MTF" -> "MTFA", "HLF 1 W" -> "HLFA 1 W".
 * Bereits-Allrad-Codes ("HLFA 2") bleiben unverändert. Codes ohne erkennbares
 * Abkürzungs-Token (kein reines Großbuchstaben-Token) werden unverändert
 * zurückgegeben.
 *
 * Diese Funktion ist die kanonische Anzeige-Hilfe des Admin-Workstreams für den
 * Allrad-Hinweis im Vorlagen-Editor.
 */
export function allradCode(code: string): string {
  const trimmed = code.trim().replace(/\s+/g, " ");
  if (trimmed === "") return trimmed;
  const spaceIdx = trimmed.indexOf(" ");
  const abk = spaceIdx === -1 ? trimmed : trimmed.slice(0, spaceIdx);
  const rest = spaceIdx === -1 ? "" : trimmed.slice(spaceIdx);

  // Nur reine Großbuchstaben-Tokens (ggf. mit Bindestrich) sind Abkürzungen.
  if (!/^[A-ZÄÖÜ-]+$/.test(abk)) return trimmed;
  // Schon Allrad? (endet auf "FA" mit valider Grundform) -> unverändert.
  if (entferneAllradInfix(abk) !== null) return trimmed;
  return `${abk}A${rest}`;
}

/**
 * Liefert die kanonische Grundform eines Codes für Gleichheitsvergleiche:
 * Großschreibung, vereinheitlichte Leerzeichen, getrimmt und das Allrad-Infix
 * entfernt. "HLFA 3" und "HLF 3" normalisieren beide auf "HLF 3".
 */
export function normalizeCode(code: string): string {
  const trimmed = code.toUpperCase().trim().replace(/\s+/g, " ");
  if (trimmed === "") return trimmed;
  const spaceIdx = trimmed.indexOf(" ");
  const abk = spaceIdx === -1 ? trimmed : trimmed.slice(0, spaceIdx);
  const rest = spaceIdx === -1 ? "" : trimmed.slice(spaceIdx);
  const grund = entferneAllradInfix(abk);
  return grund === null ? trimmed : `${grund}${rest}`;
}

/** true, wenn zwei Codes (nach Normalisierung inkl. Allrad-Infix) gleich sind. */
export function codesMatch(a: string, b: string): boolean {
  return normalizeCode(a) === normalizeCode(b);
}
