import { useState, useEffect, useMemo, useRef, type TouchEventHandler } from 'react';
import { Card, Button, Modal, message } from 'antd';
import { useNavigate, useLocation } from 'react-router-dom';
import { useUser, useQuiz } from '../contexts';
import { quizAPI } from '../services/api';
import { questionTypeMap } from '../utils/validation';
import { detectHorizontalSwipe } from '../utils/swipe';
import { UserLayout } from '../layouts/UserLayout';
import { QuizHeader } from './quiz/components/QuizHeader';
import { QuizProgress } from './quiz/components/QuizProgress';
import { OptionList } from './quiz/components/OptionList';
import { QuizFooter } from './quiz/components/QuizFooter';

interface Question {
  id: string;
  content: string;
  type: 'single' | 'multiple' | 'judgment' | 'text';
  options?: string[];
  answer: string | string[];
  analysis?: string;
  score: number;
  createdAt: string;
  category?: string;
}

interface LocationState {
  questions?: Question[];
  totalScore?: number;
  timeLimit?: number;
  subjectId?: string;
  taskId?: string;
  taskName?: string;
}

const QuizPage = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const { user } = useUser();
  const { questions, setQuestions, currentQuestionIndex, setCurrentQuestionIndex, answers, setAnswer, setAnswers, clearQuiz } = useQuiz();
  const [loading, setLoading] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [answerSheetOpen, setAnswerSheetOpen] = useState(false);
  const [timeLeft, setTimeLeft] = useState<number | null>(null);
  const [timeLimit, setTimeLimit] = useState<number | null>(null);
  const [subjectId, setSubjectId] = useState<string>('');
  const [taskId, setTaskId] = useState<string>('');
  const [taskName, setTaskName] = useState<string>('');
  const lastTickSavedAtMsRef = useRef<number>(0);
  const saveDebounceTimerRef = useRef<number | null>(null);
  const [navDirection, setNavDirection] = useState<'next' | 'prev'>('next');
  const [enterAnimationOn, setEnterAnimationOn] = useState(false);
  const touchStartRef = useRef<{ x: number; y: number; time: number } | null>(null);
  const questionHeadingRef = useRef<HTMLHeadingElement | null>(null);

  useEffect(() => {
    const el = questionHeadingRef.current;
    if (!el) return;
    el.focus();
  }, [currentQuestionIndex]);

  useEffect(() => {
    const onKeyDown = (event: KeyboardEvent) => {
      if (event.defaultPrevented) return;

      const active = document.activeElement as HTMLElement | null;
      const activeTag = (active?.tagName || '').toLowerCase();

      const inputType =
        activeTag === 'input' ? ((active as HTMLInputElement | null)?.type || '').toLowerCase() : '';
      const isTextualInputType =
        activeTag === 'input'
          ? inputType === '' ||
            inputType === 'text' ||
            inputType === 'search' ||
            inputType === 'tel' ||
            inputType === 'url' ||
            inputType === 'email' ||
            inputType === 'password' ||
            inputType === 'number'
          : false;
      const inTextInput =
        activeTag === 'textarea' ||
        active?.getAttribute('role') === 'textbox' ||
        active?.classList.contains('ant-input') ||
        active?.closest?.('.ant-input') ||
        isTextualInputType ||
        active?.isContentEditable;

      if (inTextInput) return;

      if (event.key === 'ArrowLeft') {
        event.preventDefault();
        handlePrevious();
        return;
      }

      if (event.key === 'ArrowRight') {
        event.preventDefault();
        handleNext();
        return;
      }

      if (event.key === 'Escape') {
        if (answerSheetOpen) {
          event.preventDefault();
          setAnswerSheetOpen(false);
        }
      }
    };

    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [answerSheetOpen, currentQuestionIndex, questions.length]);

  useEffect(() => {
    if (!user) {
      message.warning('请先填写个人信息');
      navigate('/');
      return;
    }

    const state = location.state as LocationState;

    clearQuiz();

    if (state?.questions) {
      const nextSubjectId = state.subjectId || '';
      const nextTaskId = state.taskId || '';
      const nextTaskName = state.taskName || '';
      const nextTimeLimit = state.timeLimit || 60;

      setQuestions(state.questions);
      setAnswers({});
      setCurrentQuestionIndex(0);
      setTimeLimit(nextTimeLimit);
      setTimeLeft(nextTimeLimit * 60);
      setSubjectId(nextSubjectId);
      setTaskId(nextTaskId);
      setTaskName(nextTaskName);

      const progressKey = buildProgressKey(user.id, nextSubjectId, nextTaskId);
      setActiveProgress(user.id, progressKey);
      saveProgress(progressKey, {
        questions: state.questions,
        answers: {},
        currentQuestionIndex: 0,
        timeLeftSeconds: nextTimeLimit * 60,
        timeLimitMinutes: nextTimeLimit,
        subjectId: nextSubjectId,
        taskId: nextTaskId,
      });
      return;
    }

    const restored = restoreActiveProgress(user.id);
    if (restored) {
      setQuestions(restored.questions);
      setAnswers(restored.answers);
      setCurrentQuestionIndex(restored.currentQuestionIndex);
      setTimeLimit(restored.timeLimitMinutes);
      setTimeLeft(restored.timeLeftSeconds);
      setSubjectId(restored.subjectId);
      setTaskId(restored.taskId);
      return;
    }

    generateQuiz();
  }, [user, navigate, location]);

  // 倒计时逻辑
  useEffect(() => {
    if (timeLeft === null || timeLeft <= 0) return;

    const timer = setInterval(() => {
      setTimeLeft(prev => {
        if (prev === null || prev <= 1) {
          clearInterval(timer);
          handleTimeUp();
          return 0;
        }
        return prev - 1;
      });
    }, 1000);

    return () => clearInterval(timer);
  }, [timeLeft]);

  const generateQuiz = async () => {
    try {
      setLoading(true);
      const response = await quizAPI.generateQuiz(user!.id);
      setQuestions(response.data.questions);
      setCurrentQuestionIndex(0);
      setAnswers({});
      setTimeLimit(60);
      setTimeLeft(60 * 60);
      setSubjectId('');
      setTaskId('');

      const progressKey = buildProgressKey(user!.id, '', '');
      setActiveProgress(user!.id, progressKey);
      saveProgress(progressKey, {
        questions: response.data.questions,
        answers: {},
        currentQuestionIndex: 0,
        timeLeftSeconds: 60 * 60,
        timeLimitMinutes: 60,
        subjectId: '',
        taskId: '',
      });
    } catch (error: any) {
      message.error(error.message || '生成试卷失败');
    } finally {
      setLoading(false);
    }
  };

  const handleTimeUp = () => {
    message.warning('考试时间已到，将自动提交答案');
    setTimeout(() => {
      handleSubmit(true);
    }, 1000);
  };

  const getTagColor = (type: string) => {
    switch (type) {
      case 'single': return 'bg-orange-100 text-orange-800 border-orange-200';
      case 'multiple': return 'bg-blue-100 text-blue-800 border-blue-200';
      case 'judgment': return 'bg-purple-100 text-purple-800 border-purple-200';
      case 'text': return 'bg-green-100 text-green-800 border-green-200';
      default: return 'bg-gray-100 text-gray-800 border-gray-200';
    }
  };

  const handleAnswerChange = (questionId: string, value: string | string[]) => {
    setAnswer(questionId, value);
  };

  useEffect(() => {
    if (!user) return;
    if (!questions.length) return;
    if (timeLeft === null) return;

    if (saveDebounceTimerRef.current !== null) {
      window.clearTimeout(saveDebounceTimerRef.current);
    }

    saveDebounceTimerRef.current = window.setTimeout(() => {
      const progressKey = getActiveProgressKey(user.id);
      if (!progressKey) return;
      saveProgress(progressKey, {
        questions,
        answers,
        currentQuestionIndex,
        timeLeftSeconds: timeLeft,
        timeLimitMinutes: timeLimit || 60,
        subjectId,
        taskId,
      });
      saveDebounceTimerRef.current = null;
    }, 300);

    return () => {
      if (saveDebounceTimerRef.current !== null) {
        window.clearTimeout(saveDebounceTimerRef.current);
        saveDebounceTimerRef.current = null;
      }
    };
  }, [user, questions, answers, currentQuestionIndex, subjectId, taskId, timeLeft, timeLimit]);

  useEffect(() => {
    if (!user) return;
    if (!questions.length) return;
    if (timeLeft === null) return;

    const now = Date.now();
    if (now - lastTickSavedAtMsRef.current < 5000) return;
    lastTickSavedAtMsRef.current = now;

    const progressKey = getActiveProgressKey(user.id);
    if (!progressKey) return;

    saveProgress(progressKey, {
      questions,
      answers,
      currentQuestionIndex,
      timeLeftSeconds: timeLeft,
      timeLimitMinutes: timeLimit || 60,
      subjectId,
      taskId,
    });
  }, [user, questions.length, timeLeft]);

  const handleNext = () => {
    if (currentQuestionIndex < questions.length - 1) {
      setNavDirection('next');
      setCurrentQuestionIndex(currentQuestionIndex + 1);
    }
  };

  const handlePrevious = () => {
    if (currentQuestionIndex > 0) {
      setNavDirection('prev');
      setCurrentQuestionIndex(currentQuestionIndex - 1);
    }
  };

  const handleJumpTo = (index: number) => {
    if (index < 0 || index >= questions.length) return;
    if (index === currentQuestionIndex) return;
    setNavDirection(index > currentQuestionIndex ? 'next' : 'prev');
    setCurrentQuestionIndex(index);
  };

  const handleJumpToFirstUnanswered = () => {
    const firstUnansweredIndex = questions.findIndex(q => Number(q.score) > 0 && !answers[q.id]);
    if (firstUnansweredIndex !== -1) {
      handleJumpTo(firstUnansweredIndex);
    }
    setAnswerSheetOpen(false);
  };

  const handleSubmit = async (forceSubmit = false) => {
    try {
      setSubmitting(true);

      if (!forceSubmit) {
        const unansweredQuestions = questions.filter(q => Number(q.score) > 0 && !answers[q.id]);
        if (unansweredQuestions.length > 0) {
          message.warning(`还有 ${unansweredQuestions.length} 道题未作答`);
          return;
        }
      }

      const answersData = questions.map(question => {
        const userAnswer = (answers[question.id] ?? '') as any;
        const isCorrect = checkAnswer(question, userAnswer);
        return {
          questionId: question.id,
          userAnswer,
          score: isCorrect ? question.score : 0,
          isCorrect
        };
      });

      const response = await quizAPI.submitQuiz({
        userId: user!.id,
        subjectId: subjectId || undefined,
        taskId: taskId || undefined,
        answers: answersData
      }) as any;

      const payload = response?.data ?? response;
      const recordId = payload?.recordId;
      if (!recordId) {
        throw new Error('提交成功但未返回记录ID');
      }

      message.success('答题提交成功！');
      clearActiveProgress(user!.id);
      navigate(`/result/${recordId}`);
    } catch (error: any) {
      message.error(error.message || '提交失败');
    } finally {
      setSubmitting(false);
    }
  };

  const handleGiveUp = () => {
    if (!user) return;
    Modal.confirm({
      title: '确认弃考？',
      content: '弃考将清空本次答题进度与计时信息，且不计入考试次数。',
      okText: '确认弃考',
      cancelText: '继续答题',
      okButtonProps: { danger: true },
      onOk: () => {
        clearActiveProgress(user.id);
        clearQuiz();
        navigate('/tasks');
      },
    });
  };

  const checkAnswer = (question: Question, userAnswer: string | string[]): boolean => {
    if (Number(question.score) === 0) return true;
    if (!userAnswer) return false;

    if (question.type === 'multiple') {
      const correctAnswers = Array.isArray(question.answer) ? question.answer : [question.answer];
      const userAnswers = Array.isArray(userAnswer) ? userAnswer : [userAnswer];
      return correctAnswers.length === userAnswers.length && 
             correctAnswers.every(answer => userAnswers.includes(answer));
    } else {
      return userAnswer === question.answer;
    }
  };

  const answeredCount = useMemo(() => {
    return questions.reduce((count, q) => (answers[q.id] || Number(q.score) === 0 ? count + 1 : count), 0);
  }, [questions, answers]);

  useEffect(() => {
    if (!questions.length) return;
    setEnterAnimationOn(false);
    const rafId = requestAnimationFrame(() => setEnterAnimationOn(true));
    return () => cancelAnimationFrame(rafId);
  }, [currentQuestionIndex, questions.length]);

  if (loading || !questions.length) {
    return (
      <UserLayout>
        <div className="flex items-center justify-center h-full min-h-[500px]">
          <div className="text-center">
            <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-mars-600 mx-auto mb-4"></div>
            <p className="text-gray-700">正在生成试卷...</p>
          </div>
        </div>
      </UserLayout>
    );
  }

  const currentQuestion = questions[currentQuestionIndex];

  const handleTouchStart: TouchEventHandler = (e) => {
    if (e.touches.length !== 1) return;
    const target = e.target as HTMLElement | null;
    if (target?.closest('textarea,input,[role="textbox"],.ant-input,.ant-checkbox-wrapper,.ant-radio-wrapper')) return;
    const touch = e.touches[0];
    touchStartRef.current = { x: touch.clientX, y: touch.clientY, time: Date.now() };
  };

  const handleTouchEnd: TouchEventHandler = (e) => {
    const start = touchStartRef.current;
    touchStartRef.current = null;
    if (!start) return;

    const touch = e.changedTouches[0];
    if (!touch) return;

    const direction = detectHorizontalSwipe({
      startX: start.x,
      startY: start.y,
      endX: touch.clientX,
      endY: touch.clientY,
      elapsedMs: Date.now() - start.time,
    });

    if (direction === 'left') {
      handleNext();
      return;
    }
    if (direction === 'right') {
      handlePrevious();
    }
  };

  return (
    <div className="min-h-screen bg-gray-50 flex flex-col">
      <QuizHeader 
        current={currentQuestionIndex + 1}
        total={questions.length}
        timeLeft={timeLeft}
        onGiveUp={handleGiveUp}
        taskName={taskName}
      />
      
      <QuizProgress 
        current={currentQuestionIndex + 1}
        total={questions.length}
      />

      <div className="flex-1 overflow-y-auto pb-24 safe-area-bottom">
        <div className="max-w-md mx-auto px-4">
          <div
            onTouchStart={handleTouchStart}
            onTouchEnd={handleTouchEnd}
            className={`
              transition-all duration-300 ease-out
              ${enterAnimationOn 
                ? 'opacity-100 translate-x-0' 
                : navDirection === 'next' 
                  ? 'opacity-0 translate-x-4' 
                  : 'opacity-0 -translate-x-4'
              }
            `}
          >
            <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-2 min-h-[280px]">
              <div className="mb-2">
                <span className={`inline-block px-1 py-0.5 rounded-md text-xs font-medium border ${getTagColor(currentQuestion.type)}`}>
                  {questionTypeMap[currentQuestion.type]}
                </span>
                {currentQuestion.category && (
                  <span className="ml-2 inline-block px-1 py-0.5 bg-gray-50 text-gray-600 text-xs rounded border border-gray-100">
                    {currentQuestion.category}
                  </span>
                )}
              </div>

              <h2
                ref={questionHeadingRef}
                tabIndex={-1}
                className="text-sm font-medium text-gray-900 leading-tight mb-3 outline-none"
              >
                {currentQuestion.content}
              </h2>

              <OptionList 
                type={currentQuestion.type}
                options={currentQuestion.options}
                value={answers[currentQuestion.id]}
                onChange={(val) => handleAnswerChange(currentQuestion.id, val)}
              />
            </div>
          </div>
        </div>
      </div>

      <QuizFooter 
        current={currentQuestionIndex}
        total={questions.length}
        onPrev={handlePrevious}
        onNext={handleNext}
        onSubmit={() => handleSubmit()}
        onOpenSheet={() => setAnswerSheetOpen(true)}
        answeredCount={answeredCount}
      />

      <Modal
        title="答题卡"
        open={answerSheetOpen}
        onCancel={() => setAnswerSheetOpen(false)}
        footer={null}
        centered
        width={340}
        destroyOnClose
      >
        <div className="flex items-center justify-between mb-3">
          <div className="text-xs text-gray-700">
            已答 <span className="text-[#00897B] font-medium">{answeredCount}</span> / {questions.length}
          </div>
          <Button
            type="primary"
            onClick={handleJumpToFirstUnanswered}
            className="bg-[#00897B] hover:bg-[#00796B] text-xs h-7 px-3"
          >
            回到当前题
          </Button>
        </div>

        <div className="grid grid-cols-5 gap-2">
          {questions.map((q, idx) => {
            const isCurrent = idx === currentQuestionIndex;
            const isAnswered = !!answers[q.id];

            let className = 'h-9 w-9 rounded-full flex items-center justify-center text-xs font-medium border transition-colors ';
            if (isCurrent) {
              className += 'border-[#00897B] bg-[#E0F2F1] text-[#00695C]';
            } else if (isAnswered) {
              className += 'border-[#00897B] bg-[#00897B] text-white';
            } else {
              className += 'border-gray-200 text-gray-600 bg-white hover:border-[#00897B]';
            }

            return (
              <button
                key={q.id}
                type="button"
                className={className}
                onClick={() => {
                  setAnswerSheetOpen(false);
                  handleJumpTo(idx);
                }}
                aria-label={`跳转到第 ${idx + 1} 题`}
              >
                {idx + 1}
              </button>
            );
          })}
        </div>
      </Modal>
    </div>
  );
};

export default QuizPage;

const QUIZ_PROGRESS_ACTIVE_PREFIX = 'quiz_progress_active_v1:';
const QUIZ_PROGRESS_PREFIX = 'quiz_progress_v1:';

type QuizProgressV1 = {
  questions: Question[];
  answers: Record<string, string | string[]>;
  currentQuestionIndex: number;
  timeLeftSeconds: number;
  timeLimitMinutes: number;
  subjectId: string;
  taskId: string;
  savedAt: string;
};

const buildProgressKey = (userId: string, subjectId: string, taskId: string) => {
  const scope = taskId ? `task:${taskId}` : `subject:${subjectId || 'none'}`;
  return `${QUIZ_PROGRESS_PREFIX}${userId}:${scope}`;
};

const setActiveProgress = (userId: string, progressKey: string) => {
  localStorage.setItem(`${QUIZ_PROGRESS_ACTIVE_PREFIX}${userId}`, progressKey);
};

const removeActiveProgress = (userId: string) => {
  localStorage.removeItem(`${QUIZ_PROGRESS_ACTIVE_PREFIX}${userId}`);
};

const getActiveProgressKey = (userId: string) => {
  return localStorage.getItem(`${QUIZ_PROGRESS_ACTIVE_PREFIX}${userId}`) || '';
};

const saveProgress = (progressKey: string, input: Omit<QuizProgressV1, 'savedAt'>) => {
  const payload: QuizProgressV1 = {
    ...input,
    savedAt: new Date().toISOString(),
  };
  localStorage.setItem(progressKey, JSON.stringify(payload));
};

const restoreActiveProgress = (userId: string): QuizProgressV1 | null => {
  const progressKey = getActiveProgressKey(userId);
  if (!progressKey) return null;

  const raw = localStorage.getItem(progressKey);
  if (!raw) return null;

  try {
    const parsed = JSON.parse(raw) as QuizProgressV1;
    if (!parsed || !Array.isArray(parsed.questions)) return null;
    if (!parsed.answers || typeof parsed.answers !== 'object') return null;
    if (typeof parsed.currentQuestionIndex !== 'number') return null;
    if (typeof parsed.timeLeftSeconds !== 'number') return null;
    if (typeof parsed.timeLimitMinutes !== 'number') return null;
    if (typeof parsed.subjectId !== 'string') return null;
    if (typeof parsed.taskId !== 'string') return null;
    return parsed;
  } catch {
    return null;
  }
};

const clearActiveProgress = (userId: string) => {
  const progressKey = getActiveProgressKey(userId);
  if (progressKey) {
    localStorage.removeItem(progressKey);
  }
  removeActiveProgress(userId);
};
