import type { EditorView } from "prosemirror-view"
import type { FormattingHandlers } from "@/lib/formatting"
import {
  getActiveHeading,
  getActiveTask,
  insertBlockMath,
  insertBlockRef,
  insertInlineMath,
  insertLink,
  insertPageRef,
  insertTag,
  isFormatActive,
  setHeading,
  toggleBold,
  toggleCode,
  toggleHighlight,
  toggleItalic,
  toggleStrikethrough,
  toggleTask,
} from "@/lib/formatting"

function withRefocus(getView: () => EditorView | null, fn: (v: EditorView) => void) {
  return () => {
    const view = getView()
    if (!view) return
    fn(view)
    requestAnimationFrame(() => view.focus())
  }
}

export function createFormattingHandlers(
  getView: () => EditorView | null,
): FormattingHandlers {
  return {
    toggleBold: withRefocus(getView, toggleBold),
    toggleItalic: withRefocus(getView, toggleItalic),
    toggleCode: withRefocus(getView, toggleCode),
    toggleStrikethrough: withRefocus(getView, toggleStrikethrough),
    toggleHighlight: withRefocus(getView, toggleHighlight),
    insertLink: (url?: string) => {
      const view = getView()
      if (!view) return
      insertLink(view, url)
      requestAnimationFrame(() => view.focus())
    },
    insertInlineMath: withRefocus(getView, insertInlineMath),
    insertBlockMath: withRefocus(getView, insertBlockMath),
    insertPageRef: (pageName: string, alias?: string) => {
      const view = getView()
      if (!view) return
      insertPageRef(view, pageName, alias)
      requestAnimationFrame(() => view.focus())
    },
    insertBlockRef: (blockId: string) => {
      const view = getView()
      if (!view) return
      insertBlockRef(view, blockId)
      requestAnimationFrame(() => view.focus())
    },
    insertTag: (tag: string) => {
      const view = getView()
      if (!view) return
      insertTag(view, tag)
      requestAnimationFrame(() => view.focus())
    },
    setHeading: (level: number | null) => {
      const view = getView()
      if (!view) return
      setHeading(view, level)
      requestAnimationFrame(() => view.focus())
    },
    toggleTask: (state?: string) => {
      const view = getView()
      if (!view) return
      toggleTask(view, state as Parameters<typeof toggleTask>[1])
      requestAnimationFrame(() => view.focus())
    },
    isActive: (format: string): boolean => {
      const view = getView()
      return view ? isFormatActive(view, format) : false
    },
    getActiveHeading: (): number | null => {
      const view = getView()
      return view ? getActiveHeading(view) : null
    },
    getActiveTask: (): string | null => {
      const view = getView()
      return view ? getActiveTask(view) : null
    },
  }
}
