"use client"

import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, forwardRef } from "react"
import { useEditor, EditorContent, type Editor } from "@tiptap/react"
import StarterKit from "@tiptap/starter-kit"
import Placeholder from "@tiptap/extension-placeholder"
import { useTranslations } from "next-intl"
import {
  Bold,
  Italic,
  List,
  ListOrdered,
  Quote,
  Redo,
  Strikethrough,
  Underline,
  Undo,
} from "lucide-react"

import { cn } from "@/shared/lib/utils"
import { Button } from "@/shared/components/ui/button"
import { Separator } from "@/shared/components/ui/separator"
import {
  BlankNode,
  DottedMark,
  GroupBlock,
  ImageNode,
  QuestionBlock,
  SectionBlock,
  type QuestionBlockType,
} from "./extensions"
import { SelectionToolbar } from "./selection-toolbar"
import type { EditorJSONContent } from "./exam-rich-editor-types"

export interface ExamRichEditorHandle {
  /** 获取当前编辑器文档(Tiptap JSONContent) */
  getJSON: () => EditorJSONContent | null
  /** 设置编辑器文档 */
  setJSON: (doc: EditorJSONContent) => void
  /** 获取纯文本(用于标题等) */
  getText: () => string
  /** 插入题目块 */
  insertQuestion: (type: QuestionBlockType, score?: number) => void
  /** 将选区包裹为题目块 */
  wrapInQuestion: (type: QuestionBlockType, score?: number) => void
  /** 插入大题分组 */
  insertGroup: (title?: string, instruction?: string) => void
  /** 将选区包裹为大题分组 */
  wrapInGroup: (title?: string, instruction?: string) => void
  /** 插入试卷分卷 */
  insertSection: (title?: string, level?: number) => void
  /** 将选区包裹为试卷分卷 */
  wrapInSection: (title?: string, level?: number) => void
  /** 清空编辑器 */
  clear: () => void
  /** 获取 Editor 实例(高级用法) */
  getEditor: () => Editor | null
}

interface ExamRichEditorProps {
  /** 初始内容(JSONContent) */
  initialContent?: EditorJSONContent | null
  /** 占位提示文本 */
  placeholder?: string
  /** 内容变化回调 */
  onChange?: (doc: EditorJSONContent) => void
  /** 是否只读 */
  readOnly?: boolean
  className?: string
}

interface ToolbarButtonProps {
  onClick: () => void
  icon: React.ElementType
  title: string
  active?: boolean
  disabled?: boolean
}

function ToolbarButton({ onClick, icon: Icon, title, active, disabled }: ToolbarButtonProps) {
  return (
    <Button
      type="button"
      variant={active ? "secondary" : "ghost"}
      size="icon"
      className={cn(
        "h-8 w-8 shrink-0",
        active && "bg-muted text-foreground hover:bg-muted"
      )}
      disabled={disabled}
      onMouseDown={(e) => e.preventDefault()}
      onClick={(e) => {
        e.preventDefault()
        onClick()
      }}
      title={title}
      aria-label={title}
    >
      <Icon className="h-4 w-4" />
    </Button>
  )
}

/**
 * 试卷富文本编辑器 —— 基于 Tiptap,集成自定义节点(题目块/大题分组/填空/加点字/图片)。
 * 选中文本时浮现 SelectionToolbar 提供快捷标记操作。
 * 通过 ref 暴露 getJSON/setJSON 等方法供父组件调用。
 */
export const ExamRichEditor = forwardRef<ExamRichEditorHandle, ExamRichEditorProps>(
  function ExamRichEditor(
    {
      initialContent,
      placeholder,
      onChange,
      readOnly = false,
      className,
    },
    ref
  ) {
    const t = useTranslations("examHomework")
    const resolvedPlaceholder = placeholder ?? t("exam.editor.contentPlaceholder")
    const containerRef = useRef<HTMLDivElement>(null)
    const onChangeRef = useRef(onChange)
    onChangeRef.current = onChange

    const extensions = useMemo(
      () => [
        StarterKit.configure({
          heading: { levels: [1, 2, 3] },
        }),
        Placeholder.configure({
          placeholder: resolvedPlaceholder,
          emptyEditorClass:
            "is-editor-empty before:content-[attr(data-placeholder)] before:text-muted-foreground before:float-left before:pointer-events-none before:h-0",
        }),
        DottedMark,
        BlankNode,
        ImageNode,
        QuestionBlock,
        GroupBlock,
        SectionBlock,
      ],
      [resolvedPlaceholder]
    )

    const editor = useEditor({
      immediatelyRender: false,
      extensions,
      editable: !readOnly,
      content: initialContent ?? undefined,
      editorProps: {
        attributes: {
          class:
            "prose prose-sm dark:prose-invert max-w-none min-h-[400px] p-4 focus:outline-none",
        },
      },
      onUpdate: ({ editor }) => {
        onChangeRef.current?.(editor.getJSON() as EditorJSONContent)
      },
    })

    // 当 initialContent 变化时(如切换试卷),重置编辑器内容
    useEffect(() => {
      if (!editor) return
      if (initialContent) {
        editor.commands.setContent(initialContent)
      }
      // 仅在 initialContent 引用变化时执行
    }, [initialContent, editor])

    useImperativeHandle(
      ref,
      (): ExamRichEditorHandle => ({
        getJSON: () => (editor ? (editor.getJSON() as EditorJSONContent) : null),
        setJSON: (doc) => {
          editor?.commands.setContent(doc)
        },
        getText: () => editor?.getText() ?? "",
        insertQuestion: (type, score = 2) => {
          editor?.chain().focus().insertQuestion({ type, score }).run()
        },
        wrapInQuestion: (type, score = 2) => {
          editor?.chain().focus().wrapInQuestion({ type, score }).run()
        },
        insertGroup: (title, instruction) => {
          editor?.chain().focus().insertGroup(title, instruction).run()
        },
        wrapInGroup: (title, instruction) => {
          editor?.chain().focus().wrapInGroup(title, instruction).run()
        },
        insertSection: (title, level) => {
          editor?.chain().focus().insertSection(title, level).run()
        },
        wrapInSection: (title, level) => {
          editor?.chain().focus().wrapInSection(title, level).run()
        },
        clear: () => {
          editor?.commands.clearContent(true)
        },
        getEditor: () => editor,
      }),
      [editor]
    )

    const handleBold = useCallback(() => {
      editor?.chain().focus().toggleBold().run()
    }, [editor])

    const handleItalic = useCallback(() => {
      editor?.chain().focus().toggleItalic().run()
    }, [editor])

    const handleStrike = useCallback(() => {
      editor?.chain().focus().toggleStrike().run()
    }, [editor])

    const handleDotted = useCallback(() => {
      editor?.chain().focus().toggleDotted().run()
    }, [editor])

    const handleBulletList = useCallback(() => {
      editor?.chain().focus().toggleBulletList().run()
    }, [editor])

    const handleOrderedList = useCallback(() => {
      editor?.chain().focus().toggleOrderedList().run()
    }, [editor])

    const handleBlockquote = useCallback(() => {
      editor?.chain().focus().toggleBlockquote().run()
    }, [editor])

    const handleUndo = useCallback(() => {
      editor?.chain().focus().undo().run()
    }, [editor])

    const handleRedo = useCallback(() => {
      editor?.chain().focus().redo().run()
    }, [editor])

    // 计算当前选区所在题目块类型(用于工具栏状态显示)
    const activeQuestionType = useMemo<QuestionBlockType | undefined>(() => {
      if (!editor) return undefined
      const $from = editor.state.selection.$from
      for (let d = $from.depth; d > 0; d--) {
        const node = $from.node(d)
        if (node.type.name === "questionBlock") {
          return (node.attrs.type as QuestionBlockType) ?? "single_choice"
        }
      }
      return undefined
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [editor, editor?.state.selection])

    if (!editor) {
      return (
        <div className={cn("flex items-center justify-center p-8 text-muted-foreground", className)}>
          {t("exam.editor.loading")}
        </div>
      )
    }

    return (
      <div
        ref={containerRef}
        className={cn(
          "relative flex flex-col rounded-md border bg-background shadow-sm overflow-hidden",
          className
        )}
      >
        {!readOnly && (
          <>
            <div className="flex flex-wrap items-center gap-1 border-b bg-background/95 p-1 backdrop-blur supports-[backdrop-filter]:bg-background/60">
              <ToolbarButton
                onClick={handleBold}
                icon={Bold}
                title={t("exam.richEditor.bold")}
                active={editor.isActive("bold")}
              />
              <ToolbarButton
                onClick={handleItalic}
                icon={Italic}
                title={t("exam.richEditor.italic")}
                active={editor.isActive("italic")}
              />
              <ToolbarButton
                onClick={handleStrike}
                icon={Strikethrough}
                title={t("exam.richEditor.strike")}
                active={editor.isActive("strike")}
              />
              <ToolbarButton
                onClick={handleDotted}
                icon={Underline}
                title={t("exam.richEditor.dotted")}
                active={editor.isActive("dotted")}
              />

              <Separator orientation="vertical" className="mx-1 h-6" />

              <ToolbarButton
                onClick={handleBulletList}
                icon={List}
                title={t("exam.richEditor.bulletList")}
                active={editor.isActive("bulletList")}
              />
              <ToolbarButton
                onClick={handleOrderedList}
                icon={ListOrdered}
                title={t("exam.richEditor.orderedList")}
                active={editor.isActive("orderedList")}
              />
              <ToolbarButton
                onClick={handleBlockquote}
                icon={Quote}
                title={t("exam.richEditor.quote")}
                active={editor.isActive("blockquote")}
              />

              <div className="ml-auto flex items-center gap-1">
                <ToolbarButton onClick={handleUndo} icon={Undo} title={t("exam.richEditor.undo")} />
                <ToolbarButton onClick={handleRedo} icon={Redo} title={t("exam.richEditor.redo")} />
              </div>
            </div>

            <SelectionToolbar editor={editor} activeQuestionType={activeQuestionType} />
          </>
        )}

        <EditorContent editor={editor} className="flex-1 overflow-y-auto min-h-0" />
      </div>
    )
  }
)
