/**
 * Shared semantic editor command registry.
 *
 * This deliberately contains no CodeMirror or ProseMirror imports. Source,
 * Visual, slash and left-+ adapters consume the same command identity/labels
 * and then execute against their own projection surface. `.tex` remains the
 * only document authority.
 */
export type LatexVisualSemanticCommand =
  | 'section'
  | 'subsection'
  | 'subsubsection'
  | 'bullet-list'
  | 'numbered-list'
  | 'inline-math'
  | 'display-math'
  | 'equation'
  | 'table'
  | 'figure'
  | 'citation'
  | 'reference'
  | 'label'
  | 'footnote'
  | 'code-block'
  | 'newline';

export type LatexEditorCommandDefinition = {
  id: string;
  label: string;
  toolbar: boolean;
  slash: readonly string[];
  /** Visual insertion identity, when the command is representable losslessly. */
  visualInsert?: LatexVisualSemanticCommand;
};

const define = (
  id: string,
  label: string,
  slash: readonly string[] = [id],
  visualInsert?: LatexVisualSemanticCommand,
): LatexEditorCommandDefinition => ({
  id,
  label,
  toolbar: true,
  slash,
  ...(visualInsert ? { visualInsert } : {}),
});

export const LATEX_EDITOR_COMMAND_DEFINITIONS: readonly LatexEditorCommandDefinition[] = [
  define('bold', 'Bold'),
  define('italic', 'Italic'),
  define('underline', 'Underline'),
  define('strikethrough', 'Strikethrough', ['strike', 'strikethrough']),
  define('emphasis', 'Emphasis', ['emphasis', 'emph']),
  define('typewriter', 'Typewriter', ['typewriter', 'monospace']),
  define('superscript', 'Superscript'),
  define('subscript', 'Subscript'),
  define('section', 'Section', ['section'], 'section'),
  define('subsection', 'Subsection', ['subsection'], 'subsection'),
  define('subsubsection', 'Subsubsection', ['subsubsection'], 'subsubsection'),
  define('itemize', 'Itemize', ['itemize', 'bullet-list'], 'bullet-list'),
  define('enumerate', 'Enumerate', ['enumerate', 'numbered-list'], 'numbered-list'),
  define('inline-math', 'Inline Math', ['math', 'inline-math'], 'inline-math'),
  define('display-math', 'Display Math', ['display-math', 'math-block'], 'display-math'),
  define('equation', 'Equation', ['equation'], 'equation'),
  define('figure', 'Figure', ['figure', 'image'], 'figure'),
  define('table', 'Table', ['table'], 'table'),
  define('verbatim', 'Verbatim', ['verbatim'], 'code-block'),
  define('listing', 'Code Listing', ['listing', 'code'], 'code-block'),
  define('hyperlink', 'Hyperlink', ['link', 'hyperlink']),
  define('citation', 'Citation', ['cite', 'citation'], 'citation'),
  define('reference', 'Reference', ['ref', 'reference'], 'reference'),
  define('label', 'Label', ['label'], 'label'),
  define('footnote', 'Footnote', ['footnote'], 'footnote'),
  define('newline', 'Line break', ['newline', 'line-break', 'hard-break'], 'newline'),
  define('text-colour', 'Text colour', ['color', 'colour', 'text-colour']),
  define('highlight', 'Highlight'),
] as const;

const COMMAND_BY_ID = new Map(
  LATEX_EDITOR_COMMAND_DEFINITIONS.map((definition) => [definition.id, definition]),
);

export function getLatexEditorCommandDefinition(
  id: string,
): LatexEditorCommandDefinition | undefined {
  return COMMAND_BY_ID.get(id);
}

export function findLatexEditorCommandDefinition(
  query: string,
): LatexEditorCommandDefinition | undefined {
  const normalized = query.trim().toLowerCase();
  return LATEX_EDITOR_COMMAND_DEFINITIONS.find(
    (definition) =>
      definition.id === normalized || definition.slash.some((alias) => alias === normalized),
  );
}
