import React, { useEffect, useState, useCallback, useRef } from 'react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import {
  $getSelection,
  $isRangeSelection,
  $isTextNode,
  TextFormatType,
  LexicalEditor,
  COMMAND_PRIORITY_NORMAL,
  COMMAND_PRIORITY_LOW,
} from 'lexical';
import { $patchStyleText, } from '@lexical/selection';
// $patchStyleText is more efficient for merging styles.

import {
  CopiedFormat,
  ACTIVATE_FORMAT_PAINTER_COMMAND,
  DEACTIVATE_FORMAT_PAINTER_COMMAND,
  FORMAT_PAINTER_STATE_UPDATE_COMMAND,
  ActivateFormatPainterPayload,
  FormatPainterState,
} from './FormatPainterCommands';

// parse style string to object for $patchStyleText
function parseStyleText(style: string): Record<string, string> {
  const styleObj: Record<string, string> = {};
  style.split(';').forEach((rule) => {
    const [key, value] = rule.split(':');
    if (key && value && key.trim() && value.trim()) {
      styleObj[key.trim()] = value.trim();
    }
  });
  return styleObj;
}

// map format flags to TextFormatType
const textFormatTypeMap: { flag: number; type: TextFormatType }[] = [
  { flag: 1, type: 'bold' },
  { flag: 2, type: 'italic' },
  { flag: 4, type: 'strikethrough' },
  { flag: 8, type: 'underline' },
  { flag: 16, type: 'code' },
  { flag: 32, type: 'subscript' },
  { flag: 64, type: 'superscript' },
];

export function FormatPainterPlugin(): null {
  const [editor] = useLexicalComposerContext();

  const [copiedFormat, setCopiedFormat] = useState<CopiedFormat | null>(null);
  const [isActive, setIsActive] = useState(false);
  const [isSticky, setIsSticky] = useState(false);

  // 避免多次复制
  const isPickingUpRef = useRef(false);

  const broadcastState = useCallback(() => {
    editor.dispatchCommand(FORMAT_PAINTER_STATE_UPDATE_COMMAND, {
      isActive,
      isSticky,
    });
  }, [editor, isActive, isSticky]);

  // Update broadcast whenever state changes
  useEffect(() => {
    broadcastState();
  }, [isActive, isSticky, broadcastState]);


  // Activate Format Painter (Copy Format)
  useEffect(() => {
    return editor.registerCommand<ActivateFormatPainterPayload>(
      ACTIVATE_FORMAT_PAINTER_COMMAND,
      (payload) => {
        isPickingUpRef.current = true;
        editor.update(() => {
          const selection = $getSelection();
          if ($isRangeSelection(selection) && !selection.isCollapsed()) {
            const anchorNode = selection.anchor.getNode();
            let formatToCopy: CopiedFormat | null = null;

            if ($isTextNode(anchorNode)) {
              formatToCopy = {
                textFormatFlags: anchorNode.getFormat(),
                style: anchorNode.getStyle(),
              };
            } else {
              // ? todo: 从第一个字符获取格式
              const nodes = selection.getNodes();
              for (const node of nodes) {
                if ($isTextNode(node)) {
                  formatToCopy = {
                    textFormatFlags: node.getFormat(),
                    style: node.getStyle(),
                  };
                  break;
                }
              }
            }

            if (formatToCopy) {
              setCopiedFormat(formatToCopy);
              setIsActive(true);
              setIsSticky(payload.sticky);
            //   console.log('Format Painter Activated. Sticky:', payload.sticky, 'Format:', formatToCopy);
            }
          }
        });
        // 鼠标抬起
        setTimeout(() => { isPickingUpRef.current = false; }, 50);
        return true;
      },
      COMMAND_PRIORITY_NORMAL,
    );
  }, [editor]);

  // Deactivate Format Painter
  useEffect(() => {
    return editor.registerCommand<void>(
      DEACTIVATE_FORMAT_PAINTER_COMMAND,
      () => {
        if (!isActive) return false;
        setIsActive(false);
        setIsSticky(false);
        // 不保留
        setCopiedFormat(null);
        // console.log('Format Painter Deactivated.');
        return true;
      },
      COMMAND_PRIORITY_NORMAL,
    );
  }, [editor, isActive]);


    // 应用复制的格式
  const applyFormat = useCallback(() => {
    if (!isActive || !copiedFormat || isPickingUpRef.current) {
      return false;
    }

    editor.update(() => {
      const selection = $getSelection();
      if ($isRangeSelection(selection) && copiedFormat) {
        // console.log('copiedFormat:', copiedFormat, '\ntextFormatTypeMap:', textFormatTypeMap);
        // TextNode (bold, italic, ...)
        textFormatTypeMap.forEach(fmt => {
            if (copiedFormat.textFormatFlags & fmt.flag) {
                selection.formatText(fmt.type);
            } else {
                const currentSelection = $getSelection();
                if ($isRangeSelection(currentSelection)) {
                   textFormatTypeMap.forEach(fmt => {
                       const shouldHaveFormat = (copiedFormat.textFormatFlags & fmt.flag) > 0;
                       if (currentSelection.hasFormat(fmt.type) !== shouldHaveFormat) {
                           currentSelection.formatText(fmt.type);
                       }
                   });
                }
            }
        });
        // ensure applied
        let newSelection = $getSelection();
        if ($isRangeSelection(newSelection)) {
            textFormatTypeMap.forEach(fmt => {
                if (copiedFormat.textFormatFlags & fmt.flag) {
                    if (!newSelection!.hasFormat(fmt.type)) newSelection!.formatText(fmt.type);
                } else {
                    if (newSelection!.hasFormat(fmt.type)) newSelection!.formatText(fmt.type);
                }
            });
        }

        // inline styles (font-family, color, font-size, ...)
        const stylesToApply = parseStyleText(copiedFormat.style);
        // console.log('inline style', stylesToApply);
        if (Object.keys(stylesToApply).length > 0) {
            newSelection = $getSelection();
            if ($isRangeSelection(newSelection)) {
                $patchStyleText(newSelection as any, stylesToApply);
            }
        } else {
            // 清除格式
            const selectedNodes = newSelection.getNodes();
            selectedNodes.forEach(node => {
              if ($isTextNode(node)) {
                if (node.getStyle() !== "") {
                  node.setStyle(""); // 清除
                }
              }
              // todo: <p> node
            });
        }

        // console.log('Format Applied. Sticky:', isSticky);

        if (!isSticky) {
          setIsActive(false);
        }
      }
    });
    return true;
  }, [editor, isActive, isSticky, copiedFormat]);


  // 鼠标抬起
  useEffect(() => {
    if (!isActive || !copiedFormat) return;

    const editorElement = editor.getRootElement();
    if (!editorElement) return;

    const handleMouseUp = (event: MouseEvent) => {
      if (isPickingUpRef.current) return;

      if (editorElement.contains(event.target as Node)) {
        // todo: 改为在下一帧更新
        setTimeout(() => {
          const selection = editor.getEditorState().read($getSelection);
          if ($isRangeSelection(selection) && !selection.isCollapsed()) {
            applyFormat();
          } else if ($isRangeSelection(selection) && selection.isCollapsed()) {
            // 折叠的选区, 也应用
            // applyFormat();
          }
        }, 0);
      }
    };

    document.addEventListener('mouseup', handleMouseUp);
    return () => {
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [editor, isActive, copiedFormat, applyFormat]);


  // 按 esc 键取消格式
  useEffect(() => {
    if (!isActive) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        editor.dispatchCommand(DEACTIVATE_FORMAT_PAINTER_COMMAND, undefined);
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [editor, isActive]);

  // 鼠标样式
  useEffect(() => {
    const editorElement = editor.getRootElement();
    if (editorElement) {
      editorElement.style.cursor = isActive ? 'copy' : 'auto';
    }
    return () => {
      if (editorElement) {
        editorElement.style.cursor = 'auto';
      }
    };
  }, [editor, isActive]);

  return null;
}
export default FormatPainterPlugin;
