/**
 * useEditor Hook
 * 编辑器初始化和管理 Hook
 */

import { useCallback, useEffect, useRef } from 'react';
import { EditorState } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { DOMSerializer } from 'prosemirror-model';
import { baseKeymap } from 'prosemirror-commands';
import { keymap } from 'prosemirror-keymap';
import { Extension } from '../core/Extension';
import { ExtensionManager } from '../core/ExtensionManager';
import { useEditorStore } from '../stores/useEditorStore';
import type { EditorContent, HeadingItem, WordCount, DocumentEditorRef } from '../core/types';

// 默认扩展
import {
  Doc,
  Text,
  Paragraph,
  Heading,
  ListItem,
  BulletList,
  OrderedList,
  Blockquote,
  CodeBlock,
  HorizontalRule,
  Image,
  Callout,
  Table,
  TableRow,
  TableCell,
} from '../extensions/nodes';
import { Bold, Italic, Code, Link, Underline, Strike, Highlight } from '../extensions/marks';
import { History, Placeholder, DropCursor, GapCursor, SlashMenuPlugin, CodeHighlight } from '../extensions/plugins';

export interface UseEditorOptions {
  extensions?: Extension[];
  content?: string | EditorContent;
  placeholder?: string;
  readOnly?: boolean;
  autoFocus?: boolean;
  onChange?: (json: string) => void;
  onFocus?: () => void;
  onBlur?: () => void;
}

export interface UseEditorReturn {
  editorRef: React.RefObject<HTMLDivElement>;
  editorMethods: DocumentEditorRef;
  isReady: boolean;
}

/**
 * 获取默认扩展列表
 */
function getDefaultExtensions(
  placeholder?: string,
  slashMenuHandlers?: {
    onOpen?: (position: { top: number; left: number }, query: string) => void;
    onClose?: () => void;
    onQueryChange?: (query: string) => void;
  }
): Extension[] {
  return [
    // 核心节点
    new Doc(),
    new Text(),
    new Paragraph(),
    new Heading(),

    // 列表节点
    new ListItem(),
    new BulletList(),
    new OrderedList(),

    // 块级节点
    new Blockquote(),
    new CodeBlock(),
    new HorizontalRule(),

    // 媒体节点
    new Image(),

    // 特殊块
    new Callout(),

    // 表格
    new Table(),
    new TableRow(),
    new TableCell(),

    // 基础标记
    new Bold(),
    new Italic(),
    new Code(),
    new Link(),
    new Underline(),
    new Strike(),
    new Highlight(),

    // 插件
    new History(),
    new Placeholder({ placeholder }),
    new DropCursor(),
    new GapCursor(),
    new SlashMenuPlugin(slashMenuHandlers),
    new CodeHighlight(),
  ];
}

/**
 * 解析内容
 */
function parseContent(content: string | EditorContent | undefined): EditorContent {
  if (!content) {
    return { type: 'doc', content: [{ type: 'paragraph' }] };
  }

  if (typeof content === 'string') {
    try {
      return JSON.parse(content) as EditorContent;
    } catch {
      // 如果解析失败，将字符串作为段落内容
      return {
        type: 'doc',
        content: [
          {
            type: 'paragraph',
            content: content ? [{ type: 'text', text: content }] : undefined,
          },
        ],
      };
    }
  }

  return content;
}

/**
 * 计算字数统计
 */
function calculateWordCount(doc: any): WordCount {
  let characters = 0;
  let words = 0;
  let paragraphs = 0;

  doc.descendants((node: any) => {
    if (node.isText) {
      characters += node.text.length;
      // 简单的中英文词汇统计
      const text = node.text.trim();
      if (text) {
        // 匹配英文单词
        const englishWords = text.match(/[a-zA-Z]+/g) || [];
        // 匹配中文字符
        const chineseChars = text.match(/[\u4e00-\u9fa5]/g) || [];
        words += englishWords.length + chineseChars.length;
      }
    }
    if (node.type.name === 'paragraph' && node.content.size > 0) {
      paragraphs++;
    }
  });

  return { characters, words, paragraphs };
}

/**
 * 提取标题列表
 */
function extractHeadings(doc: any): HeadingItem[] {
  const headings: HeadingItem[] = [];
  let headingId = 0;

  doc.descendants((node: any, pos: number) => {
    if (node.type.name === 'heading') {
      headingId++;
      const text = node.textContent;
      headings.push({
        id: node.attrs.id || `heading-${headingId}`,
        level: node.attrs.level,
        text,
        pos,
      });
    }
  });

  return headings;
}

export function useEditor(options: UseEditorOptions = {}): UseEditorReturn {
  const {
    extensions: customExtensions,
    content,
    placeholder,
    readOnly = false,
    autoFocus = false,
    onChange,
    onFocus,
    onBlur,
  } = options;

  const editorRef = useRef<HTMLDivElement>(null);
  const viewRef = useRef<EditorView | null>(null);
  const managerRef = useRef<ExtensionManager | null>(null);
  const isReadyRef = useRef(false);

  const {
    setView,
    setSchema,
    setFocused,
    setReadOnly,
    updateWordCount,
    updateHeadings,
    openSlashMenu,
    closeSlashMenu,
    setSlashMenuQuery,
    setSlashMenuItems,
    reset,
  } = useEditorStore();

  // 初始化编辑器
  useEffect(() => {
    if (!editorRef.current) return;

    // 斜杠菜单处理函数
    const slashMenuHandlers = {
      onOpen: (position: { top: number; left: number }, query: string) => {
        openSlashMenu(position, query);
      },
      onClose: () => {
        closeSlashMenu();
      },
      onQueryChange: (query: string) => {
        setSlashMenuQuery(query);
      },
    };

    // 获取扩展
    const extensions = customExtensions || getDefaultExtensions(placeholder, slashMenuHandlers);

    // 创建扩展管理器
    const manager = new ExtensionManager({ extensions });
    managerRef.current = manager;

    const schema = manager.schema;
    setSchema(schema);

    // 设置斜杠菜单项（从扩展收集）
    setSlashMenuItems(manager.slashMenuItems);

    // 解析初始内容
    const initialContent = parseContent(content);
    const doc = schema.nodeFromJSON(initialContent);

    // 创建 EditorState
    const state = EditorState.create({
      doc,
      plugins: [
        ...manager.plugins,
        keymap(baseKeymap),
      ],
    });

    // 创建 EditorView
    const view = new EditorView(editorRef.current, {
      state,
      editable: () => !readOnly,
      dispatchTransaction(transaction) {
        const newState = view.state.apply(transaction);
        view.updateState(newState);

        // 触发 onChange
        if (transaction.docChanged && onChange) {
          const json = JSON.stringify(newState.doc.toJSON());
          onChange(json);
        }

        // 更新统计信息
        if (transaction.docChanged) {
          updateWordCount(calculateWordCount(newState.doc));
          updateHeadings(extractHeadings(newState.doc));
        }
      },
      handleDOMEvents: {
        focus: () => {
          setFocused(true);
          onFocus?.();
          return false;
        },
        blur: () => {
          setFocused(false);
          onBlur?.();
          return false;
        },
      },
    });

    viewRef.current = view;
    setView(view);
    setReadOnly(readOnly);

    // 初始统计
    updateWordCount(calculateWordCount(doc));
    updateHeadings(extractHeadings(doc));

    isReadyRef.current = true;

    // 自动聚焦
    if (autoFocus) {
      setTimeout(() => view.focus(), 0);
    }

    // 清理
    return () => {
      view.destroy();
      manager.destroy();
      viewRef.current = null;
      managerRef.current = null;
      isReadyRef.current = false;
      reset();
    };
  }, []); // 只在挂载时初始化

  // 更新只读状态
  useEffect(() => {
    if (viewRef.current) {
      setReadOnly(readOnly);
      // 强制重新渲染以应用 editable 状态
      viewRef.current.setProps({
        editable: () => !readOnly,
      });
    }
  }, [readOnly, setReadOnly]);

  // 编辑器方法
  const getJSON = useCallback((): EditorContent => {
    if (!viewRef.current) {
      return { type: 'doc', content: [] };
    }
    return viewRef.current.state.doc.toJSON() as EditorContent;
  }, []);

  const getHTML = useCallback((): string => {
    if (!viewRef.current || !managerRef.current) {
      return '';
    }
    const { state } = viewRef.current;
    const schema = managerRef.current.schema;
    const serializer = DOMSerializer.fromSchema(schema);
    const fragment = serializer.serializeFragment(state.doc.content);

    const div = document.createElement('div');
    div.appendChild(fragment);
    return div.innerHTML;
  }, []);

  const getMarkdown = useCallback((): string => {
    if (!viewRef.current) {
      return '';
    }
    // 动态导入 Markdown 序列化器以减少初始包大小
    const { serializeToMarkdown } = require('../utils/markdownSerializer');
    return serializeToMarkdown(viewRef.current.state.doc);
  }, []);

  const setContent = useCallback((newContent: string | EditorContent) => {
    if (!viewRef.current || !managerRef.current) {
      return;
    }

    const schema = managerRef.current.schema;
    const parsedContent = parseContent(newContent);
    const doc = schema.nodeFromJSON(parsedContent);

    const tr = viewRef.current.state.tr.replaceWith(
      0,
      viewRef.current.state.doc.content.size,
      doc.content
    );

    viewRef.current.dispatch(tr);
  }, []);

  const isEmpty = useCallback((): boolean => {
    if (!viewRef.current) {
      return true;
    }
    const { doc } = viewRef.current.state;
    return (
      doc.childCount === 1 &&
      doc.firstChild?.isTextblock &&
      doc.firstChild.content.size === 0
    );
  }, []);

  const getHeadings = useCallback((): HeadingItem[] => {
    if (!viewRef.current) {
      return [];
    }
    return extractHeadings(viewRef.current.state.doc);
  }, []);

  const getWordCount = useCallback((): WordCount => {
    if (!viewRef.current) {
      return { characters: 0, words: 0, paragraphs: 0 };
    }
    return calculateWordCount(viewRef.current.state.doc);
  }, []);

  const focus = useCallback(() => {
    viewRef.current?.focus();
  }, []);

  const blur = useCallback(() => {
    (viewRef.current?.dom as HTMLElement)?.blur();
  }, []);

  const getView = useCallback(() => viewRef.current, []);

  const getState = useCallback(() => viewRef.current?.state ?? null, []);

  const editorMethods: DocumentEditorRef = {
    getJSON,
    getHTML,
    getMarkdown,
    setContent,
    isEmpty,
    getHeadings,
    getWordCount,
    focus,
    blur,
    getView,
    getState,
  };

  return {
    editorRef,
    editorMethods,
    isReady: isReadyRef.current,
  };
}
