import React, { useEffect, useCallback, useState, useRef } from 'react'
import { callCommand } from '@milkdown/utils'
import { toggleStrongCommand, toggleEmphasisCommand } from '@milkdown/preset-commonmark'
import { useTabStore } from '../../stores/tabStore'
import { useMilkdown } from './useMilkdown'
import { EditorToolbar } from './EditorToolbar'
import { SearchReplace } from '../SearchReplace'
import { setEditorViewGetter } from '../../stores/editorStore'

interface EditorProps {
  darkMode: boolean
}

export const Editor = React.memo(function Editor({ darkMode }: EditorProps) {
  const activeTab = useTabStore(s => s.getActiveTab())
  const activeTabId = useTabStore(s => s.activeTabId)
  const updateTabContent = useTabStore(s => s.updateTabContent)
  const setModified = useTabStore(s => s.setModified)
  const updateTabScroll = useTabStore(s => s.updateTabScroll)
  const [showSearch, setShowSearch] = useState(false)
  const currentContentRef = useRef('')

  const {
    containerRef,
    action,
    setContent,
    getScrollTop,
    setScrollTop,
    getSelection,
    setSelection,
    getView
  } = useMilkdown({
    content: activeTab?.content ?? '',
    onChange: useCallback((value: string) => {
      if (!activeTabId) return
      // B-02: 内容未变时跳过（例如纯选择变更触发的 markdownUpdated），
      // 避免将文档误标记为已修改
      const tab = useTabStore.getState().tabs.find(t => t.id === activeTabId)
      if (tab?.content === value) return
      updateTabContent(activeTabId, value)
      setModified(activeTabId, true)
    }, [activeTabId, updateTabContent, setModified]),
    darkMode
  })

  // Load content when switching tabs (only trigger on tab switch, not content edits)
  useEffect(() => {
    if (!activeTab) return
    if (activeTab.content !== currentContentRef.current) {
      currentContentRef.current = activeTab.content
      // Queue setContent after Milkdown editor has finished async create()
      requestAnimationFrame(() => {
        setContent(activeTab.content)
        requestAnimationFrame(() => {
          setScrollTop(activeTab.scrollTop)
          setSelection()
        })
      })
    }
    // stable refs: setContent, setScrollTop, setSelection are useCallback([]) - never change
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeTabId])

  // Save current tab state on unmount or tab switch
  useEffect(() => {
    return () => {
      if (!activeTabId) return
      // Snapshot the current editor state before the new tab replaces content
      const scrollPos = getScrollTop()
      const sel = getSelection()
      // Use a microtask to ensure we save before React re-renders the new tab content
      Promise.resolve().then(() => {
        updateTabScroll(activeTabId, {
          scrollTop: scrollPos,
          selectionStart: sel.from,
          selectionEnd: sel.to
        })
      })
    }
    // stable refs: getScrollTop, getSelection (useCallback([])), updateTabScroll (zustand) - never change
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeTabId])

  // Register getView for OutlinePanel navigation
  useEffect(() => {
    setEditorViewGetter(getView)
    return () => setEditorViewGetter(() => null)
  }, [getView])

  // Ctrl+B bold, Ctrl+I italic, Ctrl+F search, Ctrl+H replace
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      const isCtrl = e.ctrlKey || e.metaKey
      if (isCtrl && e.key === 'b') {
        e.preventDefault()
        action((editor) => {
          editor.action(callCommand(toggleStrongCommand.key))
        })
      }
      if (isCtrl && e.key === 'i') {
        e.preventDefault()
        action((editor) => {
          editor.action(callCommand(toggleEmphasisCommand.key))
        })
      }
      if (isCtrl && (e.key === 'f' || e.key === 'h')) {
        e.preventDefault()
        setShowSearch(true)
      }
    }
    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [action])

  return (
    <div className="editor-container" role="region" aria-label="Markdown编辑器">
      <EditorToolbar action={action} />
      {showSearch && (
        <SearchReplace
          getView={getView}
          onClose={() => setShowSearch(false)}
        />
      )}
      <div ref={containerRef} className="milkdown-wrapper" />
    </div>
  )
})

Editor.displayName = 'Editor'
