// Befehls-Registry (docs/design/rhino-command-system.md §3.2) — `COMMANDS` +
// Aliase + Präfix-Autocomplete. Einzelne Befehle leben als eigene Module unter
// `cmds/`, sodass weitere Befehle ADDITIV (ohne Änderung an Engine/App)
// dazukommen: hier importieren + registrieren, fertig.

import type { Command } from "./types";
import { lineCommand } from "./cmds/line";
import { polylineCommand } from "./cmds/polyline";
import { wallCommand } from "./cmds/wall";
import { ceilingCommand } from "./cmds/ceiling";
import { openingCommand, fensterCommand, tuerCommand } from "./cmds/opening";
import { stairCommand } from "./cmds/stair";
import { columnCommand } from "./cmds/column";
import { roomCommand } from "./cmds/room";
import { rectCommand } from "./cmds/rect";
import { circleCommand } from "./cmds/circle";
import { arcCommand } from "./cmds/arc";
import { textCommand } from "./cmds/text";
import { textboxCommand } from "./cmds/textbox";
import { moveCommand } from "./cmds/move";
import { mirrorCommand } from "./cmds/mirror";
import { joinCommand } from "./cmds/join";
import { copyCommand } from "./cmds/copy";
import { offsetCommand } from "./cmds/offset";
import { extrudeCommand } from "./cmds/extrude";
import { trimCommand } from "./cmds/trim";
import { importCommand } from "./cmds/import";
import { terrainCommand } from "./cmds/terrain";
import { measureCommand } from "./cmds/measure";

/** Alle bekannten Befehle, Schlüssel = Befehlsname (lowercase). */
export const COMMANDS: Record<string, Command> = {
  wall: wallCommand,
  ceiling: ceilingCommand,
  opening: openingCommand,
  fenster: fensterCommand,
  tuer: tuerCommand,
  stair: stairCommand,
  column: columnCommand,
  room: roomCommand,
  line: lineCommand,
  polyline: polylineCommand,
  rect: rectCommand,
  circle: circleCommand,
  arc: arcCommand,
  text: textCommand,
  textbox: textboxCommand,
  move: moveCommand,
  mirror: mirrorCommand,
  join: joinCommand,
  copy: copyCommand,
  offset: offsetCommand,
  extrude: extrudeCommand,
  trim: trimCommand,
  import: importCommand,
  terrain: terrainCommand,
  measure: measureCommand,
};

/**
 * Aliase / Kürzel → Befehlsname (§2.2). Werden VOR dem Autocomplete gematcht
 * (case-insensitiv). Minimal: Einzelbuchstaben. NICHT `r` (kollidiert mit dem
 * relativ-Koordinaten-Präfix `r5,3`).
 */
export const ALIASES: Record<string, string> = {
  w: "wall",
  wand: "wall",
  d: "ceiling",
  decke: "ceiling",
  f: "fenster",
  t: "tuer",
  tür: "tuer",
  oe: "opening",
  treppe: "stair",
  tp: "stair",
  stuetze: "column",
  stütze: "column",
  raum: "room",
  rm: "room",
  l: "line",
  pl: "polyline",
  rec: "rect",
  c: "circle",
  a: "arc",
  bogen: "arc",
  tx: "text",
  txt: "text",
  beschriftung: "text",
  m: "move",
  s: "mirror",
  spiegeln: "mirror",
  j: "join",
  verbinden: "join",
  cp: "copy",
  o: "offset",
  ex: "extrude",
  tr: "trim",
  imp: "import",
  ter: "terrain",
};

/** Liefert den Befehl zu einem exakten Namen (oder undefined). */
export function getCommand(name: string): Command | undefined {
  return COMMANDS[name.toLowerCase()];
}

/**
 * Löst eine getippte Eingabe zu einem Befehl auf: erst exakter Name, dann Alias,
 * dann eindeutiges Präfix (case-insensitiv). Mehrdeutige/leere Präfixe → null.
 */
export function resolveCommand(raw: string): Command | null {
  const q = raw.trim().toLowerCase();
  if (q === "") return null;
  if (COMMANDS[q]) return COMMANDS[q];
  if (ALIASES[q]) return COMMANDS[ALIASES[q]] ?? null;
  const matches = autocomplete(q);
  if (matches.length === 1) return COMMANDS[matches[0]] ?? null;
  // Exaktes Präfix, das auch ein Alias ist, hat Vorrang, wenn eindeutig.
  return null;
}

/**
 * Präfix-Autocomplete: alle Befehlsnamen, die mit dem (lowercase) Präfix
 * beginnen, alphabetisch. Aliase werden NICHT mitgelistet (sie sind Kürzel,
 * keine Vorschläge), aber ein exakter Alias-Treffer wird vorangestellt.
 */
export function autocomplete(prefix: string): string[] {
  const q = prefix.trim().toLowerCase();
  if (q === "") return Object.keys(COMMANDS).sort();
  const names = Object.keys(COMMANDS)
    .filter((n) => n.startsWith(q))
    .sort();
  return names;
}
