import { useEffect, useMemo, useRef, useState } from 'react'
import { motion } from 'framer-motion'
import { Link } from 'react-router-dom'
import clsx from 'clsx'
import {
  AlertTriangle,
  BarChart3,
  CheckCircle2,
  GitBranch,
  GraduationCap,
  Handshake,
  RefreshCw,
  Rocket,
  Target,
  Users,
  Workflow,
  XCircle,
} from 'lucide-react'
import { CelebrationAnimation } from '@/components/practice/CelebrationAnimation'
import {
  performanceDomains,
  performanceDomainMap,
} from '@/data/performance-domains'

type QuestionKind = 'expectedGoal' | 'keyPoint'
type PracticeScope = 'all' | QuestionKind

interface PracticeQuestion {
  id: string
  domainId: string
  kind: QuestionKind
  text: string
}

interface PracticeProgress {
  scope: PracticeScope
  queue: string[]
  completedIds: string[]
  totalCount: number
  correctCount: number
  wrongCount: number
}

interface AnswerState {
  selectedDomainId: string
  correctDomainId: string
  isCorrect: boolean
}

const STORAGE_KEY = 'performance-domain-practice-progress-v3'
const CORRECT_AUTO_NEXT_DELAY = 1000

const scopeOptions: Array<{ value: PracticeScope; label: string }> = [
  { value: 'all', label: '全部' },
  { value: 'expectedGoal', label: '预期目标' },
  { value: 'keyPoint', label: '绩效要点' },
]

const kindLabelMap: Record<QuestionKind, string> = {
  expectedGoal: '预期目标',
  keyPoint: '绩效要点',
}

const iconMap = {
  PD01: Handshake,
  PD02: Users,
  PD03: GitBranch,
  PD04: Target,
  PD05: Workflow,
  PD06: Rocket,
  PD07: BarChart3,
  PD08: AlertTriangle,
} as const

function shuffleArray<T>(items: T[]): T[] {
  const result = [...items]
  for (let i = result.length - 1; i > 0; i -= 1) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[result[i], result[j]] = [result[j], result[i]]
  }
  return result
}

function buildQuestionBank(): PracticeQuestion[] {
  return performanceDomains.flatMap((domain) => {
    const detail = domain.detail
    if (!detail) return []

    const expectedGoalQuestions = detail.expectedGoals.map((text, index) => ({
      id: `${domain.id}-goal-${index}`,
      domainId: domain.id,
      kind: 'expectedGoal' as const,
      text,
    }))

    const keyPointQuestions = detail.keyPoints.map((text, index) => ({
      id: `${domain.id}-point-${index}`,
      domainId: domain.id,
      kind: 'keyPoint' as const,
      text,
    }))

    return [...expectedGoalQuestions, ...keyPointQuestions]
  })
}

function createProgress(
  scope: PracticeScope,
  questions: PracticeQuestion[]
): PracticeProgress {
  const filteredIds = questions
    .filter((question) => (scope === 'all' ? true : question.kind === scope))
    .map((question) => question.id)

  return {
    scope,
    queue: shuffleArray(filteredIds),
    completedIds: [],
    totalCount: filteredIds.length,
    correctCount: 0,
    wrongCount: 0,
  }
}

function getStoredProgress(questions: PracticeQuestion[]): PracticeProgress {
  const questionIdSet = new Set(questions.map((question) => question.id))

  try {
    const saved = localStorage.getItem(STORAGE_KEY)
    if (!saved) return createProgress('all', questions)

    const parsed = JSON.parse(saved) as Partial<PracticeProgress>
    const scope =
      parsed.scope === 'all' ||
      parsed.scope === 'expectedGoal' ||
      parsed.scope === 'keyPoint'
        ? parsed.scope
        : 'all'

    const filteredIds = questions
      .filter((question) => (scope === 'all' ? true : question.kind === scope))
      .map((question) => question.id)
    const validIdSet = new Set(filteredIds)

    const completedIds = Array.isArray(parsed.completedIds)
      ? parsed.completedIds.filter(
          (id, index, array): id is string =>
            questionIdSet.has(String(id)) &&
            validIdSet.has(String(id)) &&
            array.indexOf(id) === index
        )
      : []

    const queue = Array.isArray(parsed.queue)
      ? parsed.queue.filter(
          (id): id is string =>
            questionIdSet.has(String(id)) &&
            validIdSet.has(String(id)) &&
            !completedIds.includes(String(id))
        )
      : []

    const missingIds = filteredIds.filter(
      (id) => !completedIds.includes(id) && !queue.includes(id)
    )

    return {
      scope,
      queue: [...queue, ...shuffleArray(missingIds)],
      completedIds,
      totalCount: filteredIds.length,
      correctCount: Math.max(Number(parsed.correctCount) || 0, 0),
      wrongCount: Math.max(Number(parsed.wrongCount) || 0, 0),
    }
  } catch (error) {
    console.error('加载绩效域练习进度失败:', error)
    return createProgress('all', questions)
  }
}

export default function PerformanceDomainPracticePage() {
  const questionBank = useMemo(() => buildQuestionBank(), [])
  const questionMap = useMemo(
    () => new Map(questionBank.map((question) => [question.id, question])),
    [questionBank]
  )

  const [progress, setProgress] = useState<PracticeProgress>(() =>
    getStoredProgress(questionBank)
  )
  const [answerState, setAnswerState] = useState<AnswerState | null>(null)
  const [showCelebration, setShowCelebration] = useState(false)
  const autoNextTimerRef = useRef<number | null>(null)

  const currentQuestionId = progress.queue[0] ?? null
  const currentQuestion = currentQuestionId
    ? questionMap.get(currentQuestionId) ?? null
    : null
  const currentDomain = currentQuestion
    ? performanceDomainMap.get(currentQuestion.domainId) ?? null
    : null
  const selectedDomain = answerState
    ? performanceDomainMap.get(answerState.selectedDomainId) ?? null
    : null
  const isFinished = progress.totalCount > 0 && progress.queue.length === 0
  const completedCount = progress.completedIds.length + (answerState?.isCorrect ? 1 : 0)
  const remainingCount = Math.max(progress.totalCount - completedCount, 0)
  const accuracyBase = progress.correctCount + progress.wrongCount
  const accuracy = accuracyBase > 0 ? Math.round((progress.correctCount / accuracyBase) * 100) : 0
  const progressPercent = progress.totalCount > 0 ? (completedCount / progress.totalCount) * 100 : 0

  useEffect(() => {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(progress))
    } catch (error) {
      console.error('保存绩效域练习进度失败:', error)
    }
  }, [progress])

  useEffect(() => {
    if (isFinished) setShowCelebration(true)
  }, [isFinished])

  useEffect(() => {
    if (!answerState?.isCorrect) return

    if (autoNextTimerRef.current) {
      window.clearTimeout(autoNextTimerRef.current)
    }

    autoNextTimerRef.current = window.setTimeout(() => {
      advanceToNext(true)
    }, CORRECT_AUTO_NEXT_DELAY)

    return () => {
      if (autoNextTimerRef.current) {
        window.clearTimeout(autoNextTimerRef.current)
        autoNextTimerRef.current = null
      }
    }
  }, [answerState])

  const restartPractice = (scope = progress.scope) => {
    if (autoNextTimerRef.current) {
      window.clearTimeout(autoNextTimerRef.current)
      autoNextTimerRef.current = null
    }
    setProgress(createProgress(scope, questionBank))
    setAnswerState(null)
    setShowCelebration(false)
  }

  const switchScope = (scope: PracticeScope) => {
    if (scope === progress.scope) return
    restartPractice(scope)
  }

  const advanceToNext = (isCorrect: boolean) => {
    if (!currentQuestionId) return

    if (autoNextTimerRef.current) {
      window.clearTimeout(autoNextTimerRef.current)
      autoNextTimerRef.current = null
    }
    setAnswerState(null)
    setProgress((prev) => {
      if (prev.queue[0] !== currentQuestionId) return prev

      const [, ...restQueue] = prev.queue
      if (isCorrect) {
        return {
          ...prev,
          queue: restQueue,
          completedIds: prev.completedIds.includes(currentQuestionId)
            ? prev.completedIds
            : [...prev.completedIds, currentQuestionId],
        }
      }

      return {
        ...prev,
        queue: [...restQueue, currentQuestionId],
      }
    })
  }

  const handleSelect = (domainId: string) => {
    if (!currentQuestion || answerState) return

    const isCorrect = domainId === currentQuestion.domainId
    setAnswerState({
      selectedDomainId: domainId,
      correctDomainId: currentQuestion.domainId,
      isCorrect,
    })
    setProgress((prev) => ({
      ...prev,
      correctCount: prev.correctCount + (isCorrect ? 1 : 0),
      wrongCount: prev.wrongCount + (isCorrect ? 0 : 1),
    }))
  }

  const renderOptionButton = (domainId: string) => {
    const domain = performanceDomainMap.get(domainId)
    if (!domain) return null

    const Icon = iconMap[domain.id as keyof typeof iconMap]
    const isAnswerShown = Boolean(answerState)
    const isSelected = answerState?.selectedDomainId === domain.id
    const isCorrectDomain = answerState?.correctDomainId === domain.id
    const isCorrectSelected = isAnswerShown && isSelected && answerState?.isCorrect
    const isWrongSelected = isAnswerShown && isSelected && !answerState?.isCorrect
    const shouldHighlightCorrect = isAnswerShown && isCorrectDomain

    return (
      <motion.button
        key={domain.id}
        type="button"
        whileTap={!isAnswerShown ? { scale: 0.98 } : undefined}
        onClick={() => handleSelect(domain.id)}
        disabled={isAnswerShown}
        className={clsx(
          'relative flex min-h-[84px] items-center gap-3 rounded-xl border bg-white p-3 text-left shadow-sm transition-colors dark:bg-gray-800',
          'border-gray-100 hover:border-indigo-200 hover:bg-indigo-50/40 dark:border-gray-700 dark:hover:border-indigo-700 dark:hover:bg-indigo-950/20',
          isAnswerShown && 'cursor-default hover:bg-white dark:hover:bg-gray-800',
          shouldHighlightCorrect &&
            'border-emerald-400 bg-emerald-50 shadow-[inset_0_0_0_2px_rgba(52,211,153,0.65)] dark:border-emerald-500 dark:bg-emerald-950/30 dark:shadow-[inset_0_0_0_2px_rgba(16,185,129,0.45)]',
          isWrongSelected &&
            'border-rose-300 bg-rose-50 dark:border-rose-700 dark:bg-rose-950/30'
        )}
      >
        <div
          className="flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-white"
          style={{ backgroundColor: domain.color }}
        >
          <Icon size={20} />
        </div>
        <div className="min-w-0 flex-1">
          <div className="text-sm font-semibold text-gray-900 dark:text-white">
            {domain.name}
          </div>
          <div className="mt-0.5 truncate text-xs text-gray-500 dark:text-gray-400">
            {domain.nameEn}
          </div>
        </div>

        {isCorrectSelected && (
          <CheckCircle2 className="absolute right-3 top-3 text-emerald-500" size={18} />
        )}
        {isWrongSelected && (
          <XCircle className="absolute right-3 top-3 text-rose-500" size={18} />
        )}
        {shouldHighlightCorrect && !isCorrectSelected && (
          <span className="absolute right-3 top-3 rounded-full bg-emerald-100 px-2 py-0.5 text-xs font-medium text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300">
            正确
          </span>
        )}
      </motion.button>
    )
  }

  return (
    <div className="mx-auto max-w-6xl space-y-4">
      {showCelebration && (
        <CelebrationAnimation onComplete={() => setShowCelebration(false)} />
      )}

      <div className="flex flex-wrap items-center justify-between gap-3">
        <div className="space-y-1">
          <nav className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
            <Link to="/performance-domains" className="hover:text-indigo-600 dark:hover:text-indigo-400">
              绩效域
            </Link>
            <span>/</span>
            <span className="text-gray-900 dark:text-white">练习</span>
          </nav>
          <div>
            <h1 className="text-xl font-bold text-gray-900 dark:text-white">八大绩效域练习</h1>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              根据预期目标和绩效要点，判断对应的绩效域。
            </p>
          </div>
        </div>

        <button
          type="button"
          onClick={() => restartPractice()}
          className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
        >
          <RefreshCw size={16} />
          重新开始
        </button>
      </div>

      <div className="rounded-2xl bg-white p-4 shadow-sm ring-1 ring-gray-100 dark:bg-gray-800 dark:ring-gray-700">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div className="flex flex-wrap gap-2">
            {scopeOptions.map((option) => {
              const isActive = option.value === progress.scope
              return (
                <button
                  key={option.value}
                  type="button"
                  onClick={() => switchScope(option.value)}
                  className={clsx(
                    'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',
                    isActive
                      ? 'bg-indigo-600 text-white'
                      : 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'
                  )}
                >
                  {option.label}
                </button>
              )
            })}
          </div>

          <div className="flex flex-wrap gap-x-5 gap-y-1 text-sm text-gray-600 dark:text-gray-300">
            <span>已完成 <b className="text-gray-900 dark:text-white">{completedCount}/{progress.totalCount}</b></span>
            <span>剩余 <b className="text-gray-900 dark:text-white">{remainingCount}</b></span>
            <span>正确率 <b className="text-gray-900 dark:text-white">{accuracy}%</b></span>
            <span>错误 <b className="text-gray-900 dark:text-white">{progress.wrongCount}</b></span>
          </div>
        </div>

        <div className="mt-4 h-2 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
          <div
            className="h-full rounded-full bg-indigo-600 transition-all duration-300"
            style={{ width: `${progressPercent}%` }}
          />
        </div>
      </div>

      {isFinished ? (
        <motion.div
          initial={{ opacity: 0, y: 10 }}
          animate={{ opacity: 1, y: 0 }}
          className="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-100 dark:bg-gray-800 dark:ring-gray-700"
        >
          <div className="bg-indigo-600 px-6 py-7 text-white">
            <div className="inline-flex items-center gap-2 rounded-full bg-white/15 px-3 py-1 text-sm">
              <GraduationCap size={16} />
              本轮完成
            </div>
            <h2 className="mt-4 text-2xl font-bold">八大绩效域练习已完成</h2>
            <p className="mt-2 text-sm text-white/80">
              共完成 {progress.totalCount} 题，错误 {progress.wrongCount} 次。
            </p>
          </div>

          <div className="grid gap-4 px-6 py-6 md:grid-cols-3">
            <div className="rounded-xl bg-gray-50 px-4 py-4 dark:bg-gray-900/40">
              <div className="text-sm text-gray-500 dark:text-gray-400">总题数</div>
              <div className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{progress.totalCount}</div>
            </div>
            <div className="rounded-xl bg-gray-50 px-4 py-4 dark:bg-gray-900/40">
              <div className="text-sm text-gray-500 dark:text-gray-400">正确率</div>
              <div className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{accuracy}%</div>
            </div>
            <div className="rounded-xl bg-gray-50 px-4 py-4 dark:bg-gray-900/40">
              <div className="text-sm text-gray-500 dark:text-gray-400">当前范围</div>
              <div className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">
                {scopeOptions.find((option) => option.value === progress.scope)?.label ?? '全部'}
              </div>
            </div>
          </div>

          <div className="flex flex-wrap gap-3 px-6 pb-6">
            <button
              type="button"
              onClick={() => restartPractice()}
              className="inline-flex items-center gap-2 rounded-xl bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-indigo-500"
            >
              <RefreshCw size={16} />
              再来一轮
            </button>
            <Link
              to="/performance-domains"
              className="inline-flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-4 py-2.5 text-sm font-semibold text-gray-700 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
            >
              返回绩效域
            </Link>
          </div>
        </motion.div>
      ) : currentQuestion ? (
        <div className="grid gap-4 xl:grid-cols-[1fr_1.45fr]">
          <section className="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-gray-100 dark:bg-gray-800 dark:ring-gray-700">
            <div className="flex items-center justify-between gap-3">
              <span className="rounded-full bg-indigo-50 px-3 py-1 text-sm font-medium text-indigo-600 dark:bg-indigo-900/40 dark:text-indigo-300">
                {kindLabelMap[currentQuestion.kind]}
              </span>
              <span className="text-sm text-gray-500 dark:text-gray-400">
                {completedCount + 1} / {progress.totalCount}
              </span>
            </div>

            <div className="flex min-h-[180px] items-center py-6 md:min-h-[220px] xl:min-h-[300px]">
              <p className="text-2xl font-semibold leading-relaxed text-gray-900 dark:text-white md:text-3xl">
                {currentQuestion.text}
              </p>
            </div>

            <div
              className={clsx(
                'min-h-[104px] rounded-xl border px-4 py-3 transition-colors',
                answerState?.isCorrect
                  ? 'border-emerald-200 bg-emerald-50 dark:border-emerald-800 dark:bg-emerald-950/30'
                  : answerState
                    ? 'border-rose-200 bg-rose-50 dark:border-rose-800 dark:bg-rose-950/30'
                    : 'border-gray-100 bg-gray-50 dark:border-gray-700 dark:bg-gray-900/30'
              )}
            >
              {answerState && currentDomain ? (
                <div className="flex h-full flex-col justify-between gap-3">
                  <div>
                    <div
                      className={clsx(
                        'flex items-center gap-2 text-sm font-semibold',
                        answerState.isCorrect
                          ? 'text-emerald-700 dark:text-emerald-300'
                          : 'text-rose-700 dark:text-rose-300'
                      )}
                    >
                      {answerState.isCorrect ? <CheckCircle2 size={17} /> : <XCircle size={17} />}
                      {answerState.isCorrect
                        ? `正确：${currentDomain.name}`
                        : `错误：你选了 ${selectedDomain?.name ?? ''}`}
                    </div>
                    {!answerState.isCorrect && (
                      <p className="mt-1 text-sm text-gray-700 dark:text-gray-300">
                        正确答案：{currentDomain.name}
                      </p>
                    )}
                  </div>

                  <button
                    type="button"
                    onClick={() => advanceToNext(answerState.isCorrect)}
                    className="self-start rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-indigo-500"
                  >
                    下一个
                  </button>
                </div>
              ) : null}
            </div>
          </section>

          <section className="grid gap-3 sm:grid-cols-2">
            {performanceDomains.map((domain) => renderOptionButton(domain.id))}
          </section>
        </div>
      ) : null}
    </div>
  )
}
