import { useEffect } from 'react'
import type React from 'react'
import { toast } from 'sonner'
import {
  useDominoStore,
  useDominoStoreInstance,
  type ImageElement,
  type TextElement,
} from '../components/canvas'

import {
  copyImageToClipboard,
  copyTextElementToClipboard,
} from '../utils/helper'
import { useZoomActions } from './use-zoom-actions'

export interface UseShortcutsProps {
  rootRef: React.RefObject<HTMLDivElement | null>
  onDelete?: (ids: string[]) => void
  onPaste?: (e: ClipboardEvent) => void
}

export function useShortcuts({ rootRef, onDelete, onPaste }: UseShortcutsProps) {
  const store = useDominoStoreInstance()
  const { stepZoom } = useZoomActions(rootRef)
  const mode = useDominoStore(s => s.mode)
  const setMode = useDominoStore(s => s.setMode)
  const setViewport = useDominoStore(s => s.setViewport)
  const undo = useDominoStore(s => s.undo)
  const redo = useDominoStore(s => s.redo)
  const selectedIds = useDominoStore(s => s.selectedIds)
  const focusedElementId = useDominoStore(s => s.focusedElementId)
  const readOnly = useDominoStore(s => s.readOnly)

  useEffect(() => {
    const isInputActive = () => {
      // 1. 如果有元素正在被聚焦（比如正在编辑文字），禁用快捷键
      if (focusedElementId) {
        const { elements } = store.getState()
        const focusedEl = elements[focusedElementId]
        if (focusedEl?.type === 'text') return true
      }

      // 2. 如果原生 DOM 的输入框处于激活状态，禁用快捷键
      const activeElement = document.activeElement
      if (!activeElement) return false
      return (
        activeElement.tagName.toLowerCase() === 'input' ||
        activeElement.tagName.toLowerCase() === 'textarea' ||
        (activeElement as HTMLElement).isContentEditable
      )
    }

    const handleKeyDown = (e: KeyboardEvent) => {
      if (isInputActive()) return

      const isMod = e.metaKey || e.ctrlKey
      const isShift = e.shiftKey

      // 1. Space -> Pan Mode
      if (e.code === 'Space' && mode !== 'pan') {
        e.preventDefault()
        setMode('pan')
      }

      // 2. Undo/Redo
      if (isMod && e.key.toLowerCase() === 'z') {
        e.preventDefault()
        if (isShift) redo()
        else undo()
      } else if (isMod && e.key.toLowerCase() === 'y') {
        e.preventDefault()
        redo()
      }

      // 3. Zoom Shortcuts
      if (isMod && (e.key === '=' || e.key === '+')) {
        e.preventDefault()
        stepZoom(1)
      }
      if (isMod && (e.key === '-' || e.key === '_')) {
        e.preventDefault()
        stepZoom(-1)
      }
      if (e.key === '0') {
        e.preventDefault()
        setViewport({ scale: 1 })
      }

      // 4. Delete
      if (e.key === 'Delete' || e.key === 'Backspace') {
        if (selectedIds.length > 0 && !readOnly) {
          e.preventDefault()
          onDelete?.(selectedIds)
        }
      }

      // 5. Select All
      if (isMod && e.key.toLowerCase() === 'a') {
        e.preventDefault()
        const { elements, setSelectedIds } = store.getState()
        setSelectedIds(Object.keys(elements))
      }

      // 6. Escape
      if (e.key === 'Escape') {
        const { setSelectedIds, setFocusedElementId } = store.getState()
        setSelectedIds([])
        setFocusedElementId(null)
        if (mode !== 'select') setMode('select')
      }

      // 7. Arrow Keys
      const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']
      if (ARROW_KEYS.includes(e.key) && selectedIds.length > 0 && !readOnly) {
        e.preventDefault()
        const step = isShift ? 10 : 1
        const dx =
          e.key === 'ArrowLeft' ? -step : e.key === 'ArrowRight' ? step : 0
        const dy =
          e.key === 'ArrowUp' ? -step : e.key === 'ArrowDown' ? step : 0
        const { moveElements } = store.getState()
        moveElements(selectedIds, dx, dy)
      }

      // 8. Copy
      if (isMod && e.key.toLowerCase() === 'c') {
        const { elements } = store.getState()
        const selectedElements = selectedIds
          .map(id => elements[id])
          .filter(Boolean)

        if (selectedElements.length === 0) return

        e.preventDefault()
        if (selectedElements.length === 1) {
          const el = selectedElements[0]
          if (el.type === 'text') {
            const textEl = el as TextElement
            copyTextElementToClipboard(textEl).then(success => {
              if (success) toast.success('已复制文本')
            })
          } else if (el.type === 'image') {
            const imageEl = el as ImageElement
            copyImageToClipboard(imageEl.id).then(success => {
              if (success) toast.success('已复制图片')
              else toast.error('复制失败')
            })
          }

          return
        }

        const texts = selectedElements
          .filter((el): el is TextElement => el.type === 'text')
          .map(el => el.content)
        if (texts.length > 0) {
          navigator.clipboard
            .writeText(texts.join('\n'))
            .then(() => toast.success(`已复制 ${texts.length} 条内容`))
        }
      }
    }

    const handleKeyUp = (e: KeyboardEvent) => {
      if (e.code === 'Space' && !isInputActive()) {
        setMode('select')
      }
    }

    const handlePaste = (e: ClipboardEvent) => {
      if (isInputActive()) return
      if (!onPaste) return
      onPaste(e)
    }

    window.addEventListener('keydown', handleKeyDown)
    window.addEventListener('keyup', handleKeyUp)
    window.addEventListener('paste', handlePaste)
    return () => {
      window.removeEventListener('keydown', handleKeyDown)
      window.removeEventListener('keyup', handleKeyUp)
      window.removeEventListener('paste', handlePaste)
    }
  }, [
    stepZoom,
    mode,
    setMode,
    setViewport,
    undo,
    redo,
    selectedIds,
    focusedElementId,
    readOnly,
    store,
    rootRef,
    onDelete,
    onPaste,
  ])
}
