import { useState, useEffect, useCallback, useRef } from 'react'
import clsx from 'clsx'
import { normalizeAnswer, announceToScreenReader } from '@/utils/practice'
import { InputArea } from '@/components/practice/InputArea'
import { CelebrationAnimation } from '@/components/practice/CelebrationAnimation'
import {
  principleGroups,
  principles,
  principleMap,
  getNextUnanswered,
  type Principle,
} from '@/data/principles'

type CharStatus = 'pending' | 'correct' | 'error'

const STORAGE_KEY = 'principles-practice-progress'

export default function PrinciplesPage() {
  const [isPracticeMode, setIsPracticeMode] = useState(false)

  // 答题进度
  const [answeredCells, setAnsweredCells] = useState<Map<string, boolean>>(
    () => new Map()
  )
  const [currentPrincipleId, setCurrentPrincipleId] = useState<string | null>(
    () => principles[0]?.id ?? null
  )

  // 输入状态
  const [userInput, setUserInput] = useState<string[]>([])
  const [charStatuses, setCharStatuses] = useState<CharStatus[]>([])
  const [isComposing, setIsComposing] = useState(false)
  const isComposingRef = useRef(false)
  const latestInputRef = useRef<string[]>([])
  const [lastErrorTimestamp, setLastErrorTimestamp] = useState<number | null>(null)

  // 显示答案
  const [showAnswerForCell, setShowAnswerForCell] = useState<{
    principleId: string
    answer: string
    expiresAt: number
  } | null>(null)
  const [inputLocked, setInputLocked] = useState(false)

  // 庆祝动画
  const [showCelebration, setShowCelebration] = useState(false)

  // 长按计时器
  const longPressTimerRef = useRef<number | null>(null)

  const currentPrinciple = currentPrincipleId
    ? (principleMap.get(currentPrincipleId) ?? null)
    : null

  const answeredCount = principles.filter((p) => answeredCells.get(p.id)).length

  // ─── 焦点恢复 ────────────────────────────────────────────────
  const restoreFocus = useCallback(() => {
    setTimeout(() => {
      const inputs = document.querySelectorAll('.practice-input-area input')
      const firstEmpty = Array.from(inputs).find(
        (el) => !(el as HTMLInputElement).value
      ) as HTMLInputElement | undefined
      if (firstEmpty) {
        firstEmpty.focus()
      } else {
        (inputs[0] as HTMLInputElement)?.focus()
      }
    }, 100)
  }, [])

  // ─── 长按显示答案 ─────────────────────────────────────────────
  const handleLongPress = useCallback((principleId: string) => {
    const principle = principleMap.get(principleId)
    if (!principle) return
    setShowAnswerForCell({
      principleId,
      answer: principle.name,
      expiresAt: Date.now() + 3000,
    })
    setInputLocked(true)
    announceToScreenReader('答案已显示')
  }, [])

  const handleLongPressEnd = useCallback(() => {
    if (showAnswerForCell) {
      setShowAnswerForCell(null)
      setInputLocked(false)
      announceToScreenReader('答案已隐藏')
      restoreFocus()
    }
  }, [showAnswerForCell, restoreFocus])

  // 答案自动过期
  useEffect(() => {
    if (!showAnswerForCell) return
    const remaining = showAnswerForCell.expiresAt - Date.now()
    if (remaining <= 0) {
      setShowAnswerForCell(null)
      setInputLocked(false)
      restoreFocus()
      return
    }
    const timer = setTimeout(() => {
      setShowAnswerForCell(null)
      setInputLocked(false)
      announceToScreenReader('答案已自动隐藏')
      restoreFocus()
    }, remaining)
    return () => clearTimeout(timer)
  }, [showAnswerForCell, restoreFocus])

  // ─── 切换题目 ─────────────────────────────────────────────────
  const switchToPrinciple = useCallback((principle: Principle) => {
    setCurrentPrincipleId(principle.id)
    setUserInput(new Array(principle.name.length).fill(''))
    setCharStatuses(new Array(principle.name.length).fill('pending'))
    setLastErrorTimestamp(null)
    requestAnimationFrame(() => {
      const el = document.querySelector(
        `[data-principle-id="${principle.id}"]`
      ) as HTMLElement | null
      el?.scrollIntoView({ behavior: 'smooth', block: 'center' })
    })
    setTimeout(() => {
      const firstInput = document.querySelector(
        '.practice-input-area input'
      ) as HTMLInputElement | null
      firstInput?.focus()
    }, 150)
  }, [])

  const moveToNextPrinciple = useCallback(() => {
    const idx = principles.findIndex((p) => p.id === currentPrincipleId)
    if (idx === -1 || idx >= principles.length - 1) return
    switchToPrinciple(principles[idx + 1])
  }, [currentPrincipleId, switchToPrinciple])

  const moveToPrevPrinciple = useCallback(() => {
    const idx = principles.findIndex((p) => p.id === currentPrincipleId)
    if (idx <= 0) return
    switchToPrinciple(principles[idx - 1])
  }, [currentPrincipleId, switchToPrinciple])

  // ─── 进度持久化 ───────────────────────────────────────────────
  const loadProgress = useCallback(() => {
    try {
      const saved = localStorage.getItem(STORAGE_KEY)
      if (saved) {
        const data = JSON.parse(saved)
        return {
          answeredCells: new Map<string, boolean>(data.answeredCells || []),
          currentPrincipleId: data.currentPrincipleId || principles[0]?.id || null,
        }
      }
    } catch (e) {
      console.error('加载原则练习进度失败:', e)
    }
    return {
      answeredCells: new Map<string, boolean>(),
      currentPrincipleId: principles[0]?.id ?? null,
    }
  }, [])

  // 进入练习模式时恢复进度
  useEffect(() => {
    if (!isPracticeMode) return
    const progress = loadProgress()
    setAnsweredCells(progress.answeredCells)
    setCurrentPrincipleId(progress.currentPrincipleId)
  }, [isPracticeMode, loadProgress])

  // 保存进度
  useEffect(() => {
    try {
      localStorage.setItem(
        STORAGE_KEY,
        JSON.stringify({
          answeredCells: Array.from(answeredCells.entries()),
          currentPrincipleId,
        })
      )
    } catch (e) {
      console.error('保存原则练习进度失败:', e)
    }
  }, [answeredCells, currentPrincipleId])

  // currentPrincipleId 变化时初始化输入框（安全网，兼容进度恢复场景）
  useEffect(() => {
    if (!isPracticeMode) return
    const principle = currentPrincipleId
      ? (principleMap.get(currentPrincipleId) ?? null)
      : null
    if (!principle) return
    setUserInput(new Array(principle.name.length).fill(''))
    setCharStatuses(new Array(principle.name.length).fill('pending'))
  }, [currentPrincipleId, isPracticeMode])

  // 同步输入快照
  useEffect(() => {
    latestInputRef.current = userInput
  }, [userInput])

  // ─── 输入验证 ─────────────────────────────────────────────────
  const validateInput = useCallback(
    (input: string[]) => {
      if (!currentPrinciple || !currentPrincipleId) return

      const originalAnswer = currentPrinciple.name
      const normalizedInput = normalizeAnswer(input.join(''), false)
      const normalizedAnswer = normalizeAnswer(originalAnswer, false)
      const normalizeChar = (char: string) => normalizeAnswer(char, false) || char

      const newStatuses = input.map((char, i) => {
        if (!char) return 'pending' as CharStatus
        const expected = originalAnswer[i] || ''
        if (!expected) return 'error' as CharStatus
        return normalizeChar(char) === normalizeChar(expected)
          ? ('correct' as CharStatus)
          : ('error' as CharStatus)
      })
      setCharStatuses(newStatuses)

      const isComplete =
        input.every((c) => c !== '') && input.length === originalAnswer.length
      const isCorrect = isComplete && normalizedInput === normalizedAnswer

      if (isCorrect) {
        const nextAnswered = new Map(answeredCells).set(currentPrincipleId, true)
        setAnsweredCells(nextAnswered)

        const allDone = principles.every((p) => nextAnswered.get(p.id))
        if (allDone) {
          setTimeout(() => setShowCelebration(true), 300)
        } else {
          const next = getNextUnanswered(currentPrincipleId, nextAnswered)
          if (next) {
            setTimeout(() => switchToPrinciple(next), 300)
          }
        }
      } else if (isComplete) {
        setLastErrorTimestamp(Date.now())
      }
    },
    [answeredCells, currentPrinciple, currentPrincipleId, switchToPrinciple]
  )

  // ─── 输入处理 ─────────────────────────────────────────────────
  const handleInputChange = useCallback(
    (newInput: string[]) => {
      latestInputRef.current = newInput
      setUserInput(newInput)
      if (isComposingRef.current) return
      validateInput(newInput)
    },
    [validateInput]
  )

  const handleCompositionStart = useCallback((_index: number) => {
    isComposingRef.current = true
    setIsComposing(true)
  }, [])

  const handleCompositionEnd = useCallback(
    (index: number, value: string) => {
      isComposingRef.current = false
      setIsComposing(false)
      requestAnimationFrame(() => {
        const current = latestInputRef.current
        const newInput = [...current]
        if (value) {
          const chars = value.split('')
          for (let i = 0; i < chars.length && index + i < newInput.length; i++) {
            newInput[index + i] = chars[i]
          }
        } else {
          newInput[index] = ''
        }
        latestInputRef.current = newInput
        setUserInput(newInput)
        validateInput(newInput)
      })
    },
    [validateInput]
  )

  const handlePaste = useCallback(
    (e: React.ClipboardEvent) => {
      e.preventDefault()
      if (!currentPrinciple) return
      const pastedText = e.clipboardData.getData('text')
      const targetLength = currentPrinciple.name.length
      const newInput = new Array(targetLength).fill('')
      const chars = pastedText.split('')
      for (let i = 0; i < Math.min(chars.length, targetLength); i++) {
        newInput[i] = chars[i]
      }
      handleInputChange(newInput)
    },
    [currentPrinciple, handleInputChange]
  )

  // ─── 长按指针事件 ─────────────────────────────────────────────
  const handlePointerDown = useCallback(
    (principleId: string) => {
      if (longPressTimerRef.current !== null) {
        clearTimeout(longPressTimerRef.current)
      }
      longPressTimerRef.current = window.setTimeout(() => {
        handleLongPress(principleId)
        longPressTimerRef.current = null
      }, 600)
    },
    [handleLongPress]
  )

  const handlePointerUp = useCallback(() => {
    if (longPressTimerRef.current !== null) {
      clearTimeout(longPressTimerRef.current)
      longPressTimerRef.current = null
    }
    // 长按已触发且答案正在显示时，松开指针立即隐藏（与 ProcessPracticePage 行为一致）
    handleLongPressEnd()
  }, [handleLongPressEnd])

  // ─── 键盘快捷键 ───────────────────────────────────────────────
  useEffect(() => {
    if (!isPracticeMode) return

    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.ctrlKey && e.key === 'h') {
        e.preventDefault()
        if (currentPrincipleId && !showAnswerForCell) {
          handleLongPress(currentPrincipleId)
        }
      } else if (e.key === 'Tab') {
        e.preventDefault()
        if (e.shiftKey) {
          moveToPrevPrinciple()
        } else {
          moveToNextPrinciple()
        }
      } else if (e.key === 'Escape' && currentPrinciple) {
        setUserInput(new Array(currentPrinciple.name.length).fill(''))
        setCharStatuses(new Array(currentPrinciple.name.length).fill('pending'))
        setLastErrorTimestamp(null)
      }
    }

    const handleKeyUp = (e: KeyboardEvent) => {
      if (e.key === 'Control' || e.key === 'h') {
        if (showAnswerForCell) handleLongPressEnd()
      }
    }

    window.addEventListener('keydown', handleKeyDown)
    window.addEventListener('keyup', handleKeyUp)
    return () => {
      window.removeEventListener('keydown', handleKeyDown)
      window.removeEventListener('keyup', handleKeyUp)
    }
  }, [
    isPracticeMode,
    currentPrinciple,
    currentPrincipleId,
    showAnswerForCell,
    handleLongPress,
    handleLongPressEnd,
    moveToNextPrinciple,
    moveToPrevPrinciple,
  ])

  // 组件卸载时清理长按计时器
  useEffect(() => {
    return () => {
      if (longPressTimerRef.current !== null) {
        clearTimeout(longPressTimerRef.current)
      }
    }
  }, [])

  // ─── 重置 ─────────────────────────────────────────────────────
  const resetPractice = useCallback(() => {
    if (!window.confirm('确定要清除练习进度吗？')) return
    setAnsweredCells(new Map())
    const first = principles[0] ?? null
    setCurrentPrincipleId(first?.id ?? null)
    if (first) {
      setUserInput(new Array(first.name.length).fill(''))
      setCharStatuses(new Array(first.name.length).fill('pending'))
    }
    setShowAnswerForCell(null)
    setInputLocked(false)
    setLastErrorTimestamp(null)
    setShowCelebration(false)
    localStorage.removeItem(STORAGE_KEY)
    announceToScreenReader('练习进度已重置')
  }, [])

  const handleCelebrationComplete = useCallback(() => {
    setShowCelebration(false)
    setAnsweredCells(new Map())
    const first = principles[0] ?? null
    setCurrentPrincipleId(first?.id ?? null)
    if (first) {
      setUserInput(new Array(first.name.length).fill(''))
      setCharStatuses(new Array(first.name.length).fill('pending'))
    }
    setShowAnswerForCell(null)
    setInputLocked(false)
    localStorage.removeItem(STORAGE_KEY)
  }, [])

  // ─── 渲染 ─────────────────────────────────────────────────────
  return (
    // 与 ProcessPracticePage 保持相同的 flex-col 布局结构
    <div className="min-h-screen bg-gray-50 dark:bg-gray-900 flex flex-col">

      {/* 顶部粘性区：标题 + 进度条 */}
      <div className="sticky top-0 z-20 bg-white dark:bg-gray-800 shadow-sm">
        <div className="max-w-7xl mx-auto px-4 py-3">
          <div className="flex items-center justify-between mb-2">
            <h1 className="text-xl font-bold text-gray-900 dark:text-gray-100">
              十二项原则
            </h1>
            <div className="flex items-center gap-3">
              {isPracticeMode && (
                <>
                  <span className="text-sm text-gray-600 dark:text-gray-400">
                    进度：{answeredCount} / {principles.length}
                  </span>
                  <button
                    type="button"
                    onClick={resetPractice}
                    className="text-xs px-2 py-1 text-gray-500 dark:text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors"
                  >
                    清除进度
                  </button>
                </>
              )}
              <div className="flex rounded-lg bg-gray-100 dark:bg-gray-700 p-0.5">
                <button
                  type="button"
                  onClick={() => setIsPracticeMode(false)}
                  className={clsx(
                    'rounded-md px-3 py-1 text-sm font-medium transition-colors',
                    !isPracticeMode
                      ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm'
                      : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'
                  )}
                >
                  查看
                </button>
                <button
                  type="button"
                  onClick={() => setIsPracticeMode(true)}
                  className={clsx(
                    'rounded-md px-3 py-1 text-sm font-medium transition-colors',
                    isPracticeMode
                      ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm'
                      : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'
                  )}
                >
                  练习
                </button>
              </div>
            </div>
          </div>
          {isPracticeMode && (
            <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
              <div
                className="bg-blue-500 h-2 rounded-full transition-all duration-300"
                style={{ width: `${(answeredCount / principles.length) * 100}%` }}
              />
            </div>
          )}
        </div>
      </div>

      {/* 中间可滚动区：原则表格 */}
      <div className="flex-1 overflow-y-auto">
        <div className="max-w-7xl mx-auto py-4 px-4">
          <div className="overflow-x-auto">
            <table className="min-w-[720px] w-full border-collapse">
              <thead>
                <tr>
                  {principleGroups.map((group) => (
                    <th
                      key={group.id}
                      className="bg-blue-700 px-4 py-3 text-center text-base font-bold text-white dark:bg-blue-800"
                    >
                      {group.label}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {[0, 1, 2, 3].map((rowIdx) => (
                  <tr key={rowIdx}>
                    {principleGroups.map((group) => {
                      const principle = group.items[rowIdx]
                      if (!principle) {
                        return (
                          <td
                            key={`${group.id}-empty`}
                            className="border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"
                          />
                        )
                      }

                      const isAnswered = !!answeredCells.get(principle.id)
                      const isCurrent =
                        isPracticeMode && principle.id === currentPrincipleId
                      const isShowingAnswer =
                        showAnswerForCell?.principleId === principle.id

                      return (
                        <td
                          key={principle.id}
                          className="border border-gray-200 dark:border-gray-700 p-0 align-top"
                        >
                          <div className="flex min-h-[72px]">
                            {/* 原则名称列 */}
                            {isPracticeMode ? (
                              <button
                                type="button"
                                data-principle-id={principle.id}
                                onClick={() => switchToPrinciple(principle)}
                                onPointerDown={() => handlePointerDown(principle.id)}
                                onPointerUp={handlePointerUp}
                                onPointerLeave={handlePointerUp}
                                onPointerCancel={handlePointerUp}
                                tabIndex={isCurrent ? 0 : -1}
                                aria-current={isCurrent ? 'step' : undefined}
                                aria-label={`原则：${principle.name}`}
                                className={clsx(
                                  'relative flex w-32 shrink-0 items-center justify-center',
                                  'border-r border-2 cursor-pointer transition-all duration-200 focus:outline-none',
                                  'border-r-gray-200 dark:border-r-gray-700',
                                  isAnswered
                                    ? 'bg-white dark:bg-gray-800 border-solid border-gray-300 dark:border-gray-600'
                                    : 'border-dashed border-gray-300 dark:border-gray-600',
                                  isCurrent && 'ring-2 ring-blue-500 border-blue-500',
                                  !isAnswered && 'min-h-[40px]'
                                )}
                              >
                                {isAnswered && (
                                  <span className="px-2 text-xs font-semibold text-gray-900 dark:text-gray-100 text-center leading-snug">
                                    {principle.name}
                                  </span>
                                )}
                                {isShowingAnswer && (
                                  <div className="absolute inset-0 flex items-center justify-center bg-black/80 rounded z-10">
                                    <span className="text-white text-sm font-medium px-2 text-center">
                                      {showAnswerForCell.answer}
                                    </span>
                                  </div>
                                )}
                              </button>
                            ) : (
                              <div className="flex w-32 shrink-0 items-center justify-center bg-blue-700 px-2 py-3 text-center text-sm font-bold leading-snug text-white dark:bg-blue-800">
                                {principle.name}
                              </div>
                            )}

                            {/* 描述列 */}
                            <div className="flex flex-1 items-center bg-white px-4 py-3 dark:bg-gray-800">
                              <p className="text-sm leading-relaxed text-gray-700 dark:text-gray-200">
                                {principle.description}
                              </p>
                            </div>
                          </div>
                        </td>
                      )
                    })}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>

      {/* 底部粘性区：练习输入（与 ProcessPracticePage 结构一致） */}
      {isPracticeMode && currentPrinciple && (
        <div className="sticky bottom-0 bg-white/60 dark:bg-gray-800/60 backdrop-blur-md border-t border-gray-200 dark:border-gray-700 z-10 pb-8">
          <div className="max-w-7xl mx-auto px-6">
            <div className="py-3 border-b border-gray-200/50 dark:border-gray-700/50">
              <div className="flex items-center justify-center gap-3">
                <InputArea
                  userInput={userInput}
                  charStatuses={charStatuses}
                  isComposing={isComposing}
                  inputLocked={inputLocked}
                  lastErrorTimestamp={lastErrorTimestamp}
                  onInputChange={handleInputChange}
                  onCompositionStart={handleCompositionStart}
                  onCompositionEnd={handleCompositionEnd}
                  onPaste={handlePaste}
                />
                <button
                  type="button"
                  onClick={() => currentPrincipleId && handleLongPress(currentPrincipleId)}
                  className="p-2 text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
                  title="查看答案（长按格子也可以）"
                >
                  <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                  </svg>
                </button>
              </div>
            </div>
            <div className="py-3 text-center text-xs text-gray-500 dark:text-gray-400">
              {currentPrinciple.description}
              <span className="ml-3 text-gray-400 dark:text-gray-500">
                · 长按格子 / Ctrl+H 查看答案 · Tab 切换
              </span>
            </div>
          </div>
        </div>
      )}

      {/* 无障碍播报区 */}
      <div
        id="aria-live-region"
        className="sr-only"
        aria-live="polite"
        aria-atomic="true"
      />

      {showCelebration && (
        <CelebrationAnimation onComplete={handleCelebrationComplete} />
      )}
    </div>
  )
}
