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
  const completedIdSet = useMemo(() => new Set(progress.completedIds), [progress.completedIds])

  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
    const getKindProgress = (kind: QuestionKind) => {
      const ids = questionBank
        .filter((question) => question.domainId === domain.id && question.kind === kind)
        .map((question) => question.id)
      const completed = ids.filter((id) => completedIdSet.has(id)).length
      return {
        completed,
        total: ids.length,
        percent: ids.length > 0 ? (completed / ids.length) * 100 : 0,
      }
    }
    const expectedGoalProgress = getKindProgress('expectedGoal')
    const keyPointProgress = getKindProgress('keyPoint')
    const expectedGoalDone = expectedGoalProgress.total > 0 && expectedGoalProgress.completed >= expectedGoalProgress.total
    const keyPointDone = keyPointProgress.total > 0 && keyPointProgress.completed >= keyPointProgress.total
    const domainDone = expectedGoalDone && keyPointDone
    const scopedDone = progress.scope === 'expectedGoal'
      ? expectedGoalDone
      : progress.scope === 'keyPoint'
        ? keyPointDone
        : domainDone
    const shouldKeepDisabled = scopedDone && !shouldHighlightCorrect && !isWrongSelected
    const optionDisabled = isAnswerShown || scopedDone

    return (
      <motion.button
        key={domain.id}
        type="button"
        whileTap={!optionDisabled ? { scale: 0.98 } : undefined}
        onClick={() => handleSelect(domain.id)}
        disabled={optionDisabled}
        className={clsx(
          'relative flex h-16 items-center justify-center overflow-hidden rounded-xl border bg-white p-1 text-center shadow-sm transition-colors dark:bg-gray-800 sm:h-[112px] sm:flex-col sm:items-stretch sm:justify-start sm:gap-2 sm:p-3 sm:text-left',
          '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',
          optionDisabled && 'cursor-default hover:bg-white dark:hover:bg-gray-800',
          shouldKeepDisabled && 'bg-gray-50 opacity-55 dark:bg-gray-800/70',
          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 shadow-[inset_0_0_0_2px_rgba(251,113,133,0.65)] dark:border-rose-600 dark:bg-rose-950/30 dark:shadow-[inset_0_0_0_2px_rgba(244,63,94,0.45)]'
        )}
      >
        <div className="hidden items-center gap-3 sm:flex">
          <div
            className={clsx(
              'flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-white',
              shouldKeepDisabled && 'grayscale'
            )}
            style={{ backgroundColor: domain.color }}
          >
            <Icon size={18} />
          </div>
          <div className="min-w-0 flex-1 pr-8">
            <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>
        </div>

        <div className="text-2xl font-bold leading-none text-gray-900 dark:text-white sm:hidden">
          {domain.name.charAt(0)}
        </div>

        <div className="hidden sm:block">
          {(() => {
            const activeProgress = progress.scope === 'expectedGoal' ? expectedGoalProgress : keyPointProgress
            const activeLabel = progress.scope === 'expectedGoal' ? '目标' : '要点'
            const isFull = activeProgress.total > 0 && activeProgress.completed >= activeProgress.total

            if (progress.scope === 'all') {
              return (
                <div className="grid grid-cols-2 gap-2">
                  {[
                    { label: '目标', data: expectedGoalProgress },
                    { label: '要点', data: keyPointProgress },
                  ].map((item) => {
                    const itemFull = item.data.total > 0 && item.data.completed >= item.data.total
                    return (
                      <div key={item.label} className="min-w-0">
                        <div className="mb-1 flex items-center justify-between gap-1 text-[11px] text-gray-500 dark:text-gray-400">
                          <span>{item.label}</span>
                          <span>{item.data.completed}/{item.data.total}</span>
                        </div>
                        <div className="h-1 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
                          <div
                            className={clsx(
                              'h-full rounded-full transition-all duration-300',
                              itemFull ? 'bg-gray-300 dark:bg-gray-500' : 'bg-indigo-500'
                            )}
                            style={{ width: `${item.data.percent}%` }}
                          />
                        </div>
                      </div>
                    )
                  })}
                </div>
              )
            }

            return (
              <div>
                <div className="mb-1 flex items-center justify-between gap-1 text-[11px] text-gray-500 dark:text-gray-400">
                  <span>{activeLabel}</span>
                  <span>{activeProgress.completed}/{activeProgress.total}</span>
                </div>
                <div className="h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
                  <div
                    className={clsx(
                      'h-full rounded-full transition-all duration-300',
                      isFull ? 'bg-gray-300 dark:bg-gray-500' : 'bg-indigo-500'
                    )}
                    style={{ width: `${activeProgress.percent}%` }}
                  />
                </div>
              </div>
            )
          })()}
        </div>

        <div className="pointer-events-none absolute right-1 top-1 flex h-4 w-8 items-center justify-end sm:right-3 sm:top-3 sm:h-5 sm:w-12">
          {isCorrectSelected && (
            <CheckCircle2 className="text-emerald-500" size={16} />
          )}
          {isWrongSelected && (
            <XCircle className="text-rose-500" size={16} />
          )}
          {shouldHighlightCorrect && !isCorrectSelected && (
            <span className="rounded-full bg-emerald-100 px-1.5 py-0.5 text-[10px] font-medium text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300 sm:px-2 sm:text-xs">
              正确
            </span>
          )}
        </div>
      </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-2xl font-semibold leading-relaxed text-indigo-600 dark:bg-indigo-900/40 dark:text-indigo-300 md:text-3xl">
                {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(
                'h-[132px] overflow-hidden 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-end 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 grid-cols-4 gap-2 sm:grid-cols-2 sm:gap-3">
            {performanceDomains.map((domain) => renderOptionButton(domain.id))}
          </section>
        </div>
      ) : null}
    </div>
  )
}
