import { snippet } from "@codemirror/autocomplete";
import type { Completion, CompletionContext, CompletionResult } from "@codemirror/autocomplete";
import type { EditorView } from "@codemirror/view";

interface SlashEntry {
  label: string;
  detail: string;
  section: string;
  apply: Completion["apply"];
}

// Insert text, replacing from the "/" character (from-1) through the cursor
function insert(text: string): Completion["apply"] {
  return (view: EditorView, _completion: Completion, from: number, to: number) => {
    view.dispatch({ changes: { from: from - 1, to, insert: text } });
  };
}

// Wrap snippet() to also replace the preceding "/" character
function slashSnippet(template: string): Completion["apply"] {
  const snip = snippet(template);
  return (view: EditorView, completion: Completion, from: number, to: number) => {
    snip(view, completion, from - 1, to - 1);
  };
}

const COMMANDS: SlashEntry[] = [
  // Headings
  { label: "H1",          detail: ">...",                    section: "Heading",  apply: slashSnippet(">\${text}") },
  { label: "H2",          detail: ">>...",                   section: "Heading",  apply: slashSnippet(">>\${text}") },
  { label: "H3",          detail: ">>>...",                  section: "Heading",  apply: slashSnippet(">>>\${text}") },

  // Text formatting
  { label: "Bold",        detail: "`!..`!",                  section: "Format",   apply: slashSnippet("`!\${text}`!") },
  { label: "Italic",      detail: "`*..`*",                  section: "Format",   apply: slashSnippet("`*\${text}`*") },
  { label: "Underline",   detail: "`_..`_",                  section: "Format",   apply: slashSnippet("`_\${text}`_") },
  { label: "Reset",       detail: "``",                      section: "Format",   apply: insert("``") },
  { label: "Literal",     detail: "`=...`=",                 section: "Format",   apply: slashSnippet("`=\n\${content}\n`=") },

  // Alignment
  { label: "Center",      detail: "`c..`a",                  section: "Align",    apply: slashSnippet("`c\${text}`a") },
  { label: "Right",       detail: "`r..`a",                  section: "Align",    apply: slashSnippet("`r\${text}`a") },
  { label: "Left",        detail: "`l..`a",                  section: "Align",    apply: slashSnippet("`l\${text}`a") },

  // Color (3-digit hex)
  { label: "Color",       detail: "`Fhex..`f",               section: "Color",    apply: slashSnippet("`F\${hex}\${text}`f") },
  { label: "BgColor",     detail: "`Bhex..`b",               section: "Color",    apply: slashSnippet("`B\${hex}\${text}`b") },

  // Links
  { label: "Link",        detail: "[label`page]",            section: "Link",     apply: slashSnippet("[\${label}`\${page}]") },

  // Dividers
  { label: "Divider ─",   detail: "-─",                      section: "Divider",  apply: insert("-─") },
  { label: "Divider ━",   detail: "-━",                      section: "Divider",  apply: insert("-━") },
  { label: "Divider ═",   detail: "-═",                      section: "Divider",  apply: insert("-═") },
  { label: "Divider ★",   detail: "-★",                      section: "Divider",  apply: insert("-★") },

  // Forms — pipe separators per micron-composer spec
  { label: "Field",       detail: "<name`default>",          section: "Form",     apply: slashSnippet("<\${name}`\${default}>") },
  { label: "Password",    detail: "<!w|name`placeholder>",   section: "Form",     apply: slashSnippet("<!\${width}|\${name}`\${placeholder}>") },
  { label: "Checkbox",    detail: "<?|name|val`label>",      section: "Form",     apply: slashSnippet("<?\${name}|\${value}`\${label}>") },
  { label: "Checked",     detail: "<?|name|val|*`label>",    section: "Form",     apply: slashSnippet("<?\${name}|\${value}|*`\${label}>") },
  { label: "Radio",       detail: "<^|grp|val`label>",       section: "Form",     apply: slashSnippet("<^\${group}|\${value}`\${label}>") },

  // Depth
  { label: "Reset depth", detail: "<",                       section: "Depth",    apply: insert("<\n") },
];

export function slashCommandSource(ctx: CompletionContext): CompletionResult | null {
  const match = ctx.matchBefore(/\/\w*/);
  if (!match || (match.from === match.to && !ctx.explicit)) return null;
  return {
    // Start after "/" so the filter text doesn't include "/" (which would block all matches)
    from: match.from + 1,
    filter: true,
    options: COMMANDS.map((cmd) => ({
      label: cmd.label,
      detail: cmd.detail,
      section: cmd.section,
      apply: cmd.apply,
      boost: 99,
    })),
  };
}
