/**
 * Minimal ProseMirror schema for markdown editor.
 *
 * Only contains structural nodes - no semantic marks (bold, italic, etc).
 * Markdown syntax is preserved as plain text and rendered via decorations.
 * hard_break preserves the \n vs \n\n distinction within block content.
 */
import { type NodeSpec, Schema } from "prosemirror-model"

type DOMNode =
  | "doc"
  | "paragraph"
  | "hard_break"
  | "code_block"
  | "math_block"
  | "text"

/** Node definitions */
const nodes: Record<DOMNode, NodeSpec> = {
  /** Root document container — one or more paragraphs per block */
  doc: {
    content: "block+",
  },
  /** Paragraph — one per line within a block */
  paragraph: {
    group: "block",
    content: "inline*",
    parseDOM: [{ tag: "p" }],
    toDOM: () => ["p", 0],
  },
  /** Hard line break — preserves single \n within a paragraph */
  hard_break: {
    inline: true,
    group: "inline",
    selectable: false,
    parseDOM: [{ tag: "br" }],
    toDOM: () => ["br"],
  },
  /** Fenced code block — rendered via CodeMirror 6 node view */
  code_block: {
    group: "block",
    content: "text*",
    code: true,
    defining: true,
    attrs: { language: { default: "" } },
    parseDOM: [
      {
        tag: "pre",
        getAttrs(dom) {
          const code = dom.querySelector("code")
          const lang = code?.className?.match(/language-(\w+)/)?.[1] ?? ""
          return { language: lang }
        },
      },
    ],
    toDOM: (node) => [
      "pre",
      { class: node.attrs.language ? `language-${node.attrs.language}` : "" },
      ["code", 0],
    ],
  },
  /** Display math block — rendered via KaTeX node view */
  math_block: {
    group: "block",
    content: "text*",
    code: true,
    defining: true,
    toDOM: () => ["div", { "data-math-block": "" }, 0],
  },
  /** Text content */
  text: {
    group: "inline",
  },
}

/** No marks - all formatting handled via decorations */
const marks = {}

export const schema = new Schema<DOMNode, never>({ nodes, marks })
