/**
 * Component registry for Comark block/inline components.
 *
 * Renderers are registered by component name (e.g., "query", "note")
 * and looked up by the MarkdownRuleEngine when a BlockComponent or
 * InlineComponent node is encountered during tree traversal.
 *
 * A renderer receives the Lezer SyntaxNode and RuleContext, and returns
 * either a BlockDecoration (for block components) or null (to skip).
 * Inline components are currently passthrough — they produce ParstedDecorations
 * when they carry attrs (typed properties), or render as inline chips when
 * they have body content.
 */
import type { SyntaxNode } from "@lezer/common"
import type {
  ParseContext,
  ParsedDecorations,
} from "@/lib/markdown-rules/types"

export type ComarkRenderer = (
  node: SyntaxNode,
  ctx: ParseContext,
) => Partial<ParsedDecorations> | null

const comarkRegistry = new Map<string, ComarkRenderer>()

export function registerComarkComponent(
  name: string,
  renderer: ComarkRenderer,
) {
  comarkRegistry.set(name, renderer)
}

export function getComarkRenderer(name: string): ComarkRenderer | undefined {
  return comarkRegistry.get(name)
}

/**
 * Widget factory for rich-content rendering inside PM decorations.
 * Keyed by component name (e.g. "query"). When the decoration pipeline
 * encounters a component block, it looks up the factory by name and
 * calls it to produce a DOM element + destroy callback.
 */
export type WidgetFactory = (attrs: string) => { dom: HTMLElement; destroy: () => void }

const widgetFactories = new Map<string, WidgetFactory>()

export function registerWidgetFactory(name: string, factory: WidgetFactory) {
  widgetFactories.set(name, factory)
}

export function getWidgetFactory(name: string): WidgetFactory | null {
  return widgetFactories.get(name) ?? null
}
