import { useEffect, useMemo, useState } from 'react';
import Taro, { useRouter } from '@tarojs/taro';
import { Button, Text, Textarea, View } from '@tarojs/components';
import RichContent from '@/components/RichContent';
import { loadCollectionQuestions, loadQuestions } from '@/services/catalog';
import {
  createPracticeSession,
  loadPracticeSessionDetail,
  type SubAnswerInput,
  type SubAnswerResult,
  submitAnswer,
  submitPracticeSession,
  toggleQuestionFavorite,
  type AnswerResult,
  type PracticeReport,
  type PracticeSession,
  type QuestionItem,
} from '@/services/learning';
import { submitFeedback } from '@/services/profile';
import { getStorage, setStorage } from '@/services/storage';
import '../student.css';

type AnswerState = {
  selectedOptions: string[];
  answerText: string;
  isCorrect: boolean | null;
  answeredAt?: string;
  selfJudged?: boolean;
  subAnswers?: SubAnswerInput[];
  subResults?: SubAnswerResult[];
};

type LocalSubAnswer = {
  selectedOptions: string[];
  answerText: string;
  selfJudgedCorrect?: boolean;
};

function plainOption(option: unknown, index: number) {
  if (typeof option === 'string') return option;
  if (option && typeof option === 'object') {
    const data = option as Record<string, unknown>;
    return String(data.text || data.content || data.label || data.value || `选项 ${index + 1}`);
  }
  return `选项 ${index + 1}`;
}

function isObjectiveQuestion(question?: QuestionItem | null) {
  if (!question) return false;
  return Array.isArray(question.options) && question.options.length > 0;
}

function isMultiQuestion(question?: QuestionItem | null) {
  if (!question) return false;
  const type = String(question.type || '').toLowerCase();
  return type.includes('multi') || (question.correctOptionIndices?.length || 0) > 1;
}

function subQuestionId(subQuestion: Record<string, unknown>, index: number) {
  const raw = subQuestion.id || subQuestion.subQuestionId || subQuestion.key;
  return typeof raw === 'string' && raw.trim() ? raw.trim() : `sub_${index + 1}`;
}

function subQuestionType(subQuestion: Record<string, unknown>) {
  return String(subQuestion.type || 'choice').toLowerCase();
}

function subQuestionOptions(subQuestion: Record<string, unknown>) {
  return Array.isArray(subQuestion.options) ? subQuestion.options : [];
}

function isObjectiveSubQuestion(subQuestion: Record<string, unknown>) {
  const type = subQuestionType(subQuestion);
  return ['choice', 'multi', 'judge', 'image'].includes(type) || subQuestionOptions(subQuestion).length > 0;
}

function isMultiSubQuestion(subQuestion: Record<string, unknown>) {
  const type = subQuestionType(subQuestion);
  const correct = subQuestion.correctOptionIndices;
  return type.includes('multi') || (Array.isArray(correct) && correct.length > 1);
}

function answerStorageKey(sessionId: string) {
  return `tiku:practice:${sessionId}:answers`;
}

function indexStorageKey(sessionId: string) {
  return `tiku:practice:${sessionId}:index`;
}

function formatDuration(seconds: number) {
  const safeSeconds = Math.max(0, Math.trunc(seconds));
  const minutes = Math.floor(safeSeconds / 60);
  const rest = safeSeconds % 60;
  return `${String(minutes).padStart(2, '0')}:${String(rest).padStart(2, '0')}`;
}

function answerLabel(state?: AnswerState) {
  if (!state) return '未答';
  if (state.isCorrect === true) return '正确';
  if (state.isCorrect === false) return '错误';
  return state.selfJudged ? '已自评' : '已答';
}

function answersFromBackend(answers?: Record<string, AnswerResult>): Record<string, AnswerState> {
  const result: Record<string, AnswerState> = {};
  for (const [questionId, answer] of Object.entries(answers || {})) {
    result[questionId] = {
      selectedOptions: Array.isArray(answer.selectedOptions) ? answer.selectedOptions : [],
      answerText: answer.answerText || '',
      isCorrect: answer.isCorrect,
      answeredAt: answer.answeredAt,
      selfJudged: answer.selfJudged,
      subAnswers: Array.isArray(answer.answerPayload?.subAnswers) ? answer.answerPayload.subAnswers : [],
      subResults: Array.isArray(answer.answerPayload?.subResults) ? answer.answerPayload.subResults : answer.subResults || [],
    };
  }
  return result;
}

function subAnswerStateFrom(answer?: AnswerState): Record<string, LocalSubAnswer> {
  const result: Record<string, LocalSubAnswer> = {};
  for (const item of answer?.subAnswers || []) {
    result[item.subQuestionId] = {
      selectedOptions: Array.isArray(item.selectedOptions) ? item.selectedOptions : [],
      answerText: item.answerText || '',
      selfJudgedCorrect: item.selfJudgedCorrect,
    };
  }
  if (!Object.keys(result).length) {
    for (const item of answer?.subResults || []) {
      result[item.subQuestionId] = {
        selectedOptions: Array.isArray(item.selectedOptions) ? item.selectedOptions : [],
        answerText: item.answerText || '',
        selfJudgedCorrect: item.selfJudged ? item.isCorrect === true : undefined,
      };
    }
  }
  return result;
}

function secondsUntil(value?: string | null) {
  if (!value) return null;
  const parsed = new Date(value).getTime();
  if (!Number.isFinite(parsed)) return null;
  return Math.max(0, Math.ceil((parsed - Date.now()) / 1000));
}

export default function StudentPracticePage() {
  const router = useRouter();
  const params = router.params || {};
  const [session, setSession] = useState<PracticeSession | null>(null);
  const [questions, setQuestions] = useState<QuestionItem[]>([]);
  const [index, setIndex] = useState(0);
  const [selected, setSelected] = useState<string[]>([]);
  const [answerText, setAnswerText] = useState('');
  const [subAnswerById, setSubAnswerById] = useState<Record<string, LocalSubAnswer>>({});
  const [feedbackText, setFeedbackText] = useState('');
  const [answerByQuestion, setAnswerByQuestion] = useState<Record<string, AnswerState>>({});
  const [favoriteByQuestion, setFavoriteByQuestion] = useState<Record<string, boolean>>({});
  const [showExplanation, setShowExplanation] = useState(false);
  const [completed, setCompleted] = useState(false);
  const [timeLeft, setTimeLeft] = useState<number | null>(null);
  const [loading, setLoading] = useState(true);
  const [report, setReport] = useState<PracticeReport | null>(null);
  const [error, setError] = useState('');

  useEffect(() => {
    const practiceSessionId = params.practiceSessionId || undefined;
    const collectionId = params.collectionId || undefined;
    const body = {
      blueprintId: params.blueprintId || undefined,
      collectionId,
      entryId: params.entryId || undefined,
      contentNodeId: params.contentNodeId || undefined,
      mode: params.mode || 'sequential',
      questionLimit: 50,
    };

    if (practiceSessionId) {
      loadPracticeSessionDetail(practiceSessionId)
        .then(payload => {
          const nextSession = payload.item;
          const backendAnswers = answersFromBackend(nextSession.answersByQuestion);
          setSession(nextSession);
          setQuestions(nextSession.questions || []);
          setAnswerByQuestion(backendAnswers);
          const savedIndex = getStorage<number>(indexStorageKey(nextSession.id));
          const firstUnanswered = (nextSession.questionIds || []).findIndex(questionId => !backendAnswers[questionId]);
          setIndex(typeof savedIndex === 'number' ? savedIndex : Math.max(0, firstUnanswered));
          const remaining = secondsUntil(nextSession.expiresAt);
          if (remaining !== null) setTimeLeft(remaining);
          if (nextSession.status === 'finished') setCompleted(true);
        })
        .catch(nextError => setError(nextError instanceof Error ? nextError.message : '练习恢复失败'))
        .finally(() => setLoading(false));
      return;
    }

    createPracticeSession(body)
      .then(async payload => {
        const nextSession = payload.item;
        setSession(nextSession);
        if (nextSession.durationMinutes) setTimeLeft(nextSession.durationMinutes * 60);
        const savedIndex = getStorage<number>(indexStorageKey(nextSession.id));
        const savedAnswers = getStorage<Record<string, AnswerState>>(answerStorageKey(nextSession.id));
        if (savedAnswers) setAnswerByQuestion(savedAnswers);
        if (typeof savedIndex === 'number') setIndex(savedIndex);
        const questionPayload = collectionId
          ? await loadCollectionQuestions(collectionId, 300)
          : await loadQuestions({
            entryId: body.entryId,
            contentNodeId: body.contentNodeId,
            questionIds: nextSession.questionIds,
            limit: Math.max(nextSession.questionIds?.length || 0, 50),
          });
        const byId = new Map((questionPayload.items || []).map(item => [item.id, item]));
        const ordered = (nextSession.questionIds || []).map(id => byId.get(id)).filter(Boolean) as QuestionItem[];
        setQuestions(ordered.length ? ordered : questionPayload.items || []);
      })
      .catch(nextError => setError(nextError instanceof Error ? nextError.message : '练习创建失败'))
      .finally(() => setLoading(false));
  }, []);

  const current = questions[index];
  const options = useMemo(() => Array.isArray(current?.options) ? current.options : [], [current]);
  const subQuestions = useMemo(
    () => (Array.isArray(current?.subQuestions) ? current.subQuestions : []) as Record<string, unknown>[],
    [current],
  );
  const hasCompositeSubQuestions = subQuestions.length > 0;
  const answerState = current ? answerByQuestion[current.id] : undefined;
  const isSubmitted = !!answerState;
  const answeredCount = Object.keys(answerByQuestion).length;
  const correctCount = Object.values(answerByQuestion).filter(item => item.isCorrect === true).length;
  const wrongCount = Object.values(answerByQuestion).filter(item => item.isCorrect === false).length;
  const progressPercent = questions.length ? Math.round((answeredCount / questions.length) * 100) : 0;

  useEffect(() => {
    if (!session) return;
    setStorage(indexStorageKey(session.id), index);
  }, [index, session?.id]);

  useEffect(() => {
    if (!session) return;
    setStorage(answerStorageKey(session.id), answerByQuestion);
  }, [answerByQuestion, session?.id]);

  useEffect(() => {
    if (!current) return;
    const state = answerByQuestion[current.id];
    setSelected(state?.selectedOptions || []);
    setAnswerText(state?.answerText || '');
    setSubAnswerById(subAnswerStateFrom(state));
    setFeedbackText('');
    setShowExplanation(!!state);
  }, [current?.id]);

  useEffect(() => {
    if (timeLeft === null || report || completed) return;
    if (timeLeft <= 0) {
      void handleSubmitSession(true);
      return;
    }
    const timer = setTimeout(() => setTimeLeft(prev => (prev === null ? null : Math.max(0, prev - 1))), 1000);
    return () => clearTimeout(timer);
  }, [timeLeft, report, completed]);

  function rememberAnswer(
    questionId: string,
    result: AnswerResult | { isCorrect: boolean | null; answeredAt?: string; selfJudged?: boolean },
    nextSelected = selected,
    nextAnswerText = answerText,
  ) {
    const nextState: AnswerState = {
      selectedOptions: [...nextSelected],
      answerText: nextAnswerText,
      isCorrect: result.isCorrect,
      answeredAt: 'answeredAt' in result ? result.answeredAt : undefined,
      selfJudged: 'selfJudged' in result ? result.selfJudged : undefined,
      subAnswers: 'answerPayload' in result && Array.isArray(result.answerPayload?.subAnswers) ? result.answerPayload.subAnswers : undefined,
      subResults: 'subResults' in result && Array.isArray(result.subResults)
        ? result.subResults
        : 'answerPayload' in result && Array.isArray(result.answerPayload?.subResults)
          ? result.answerPayload.subResults
          : undefined,
    };
    setAnswerByQuestion(prev => ({ ...prev, [questionId]: nextState }));
    setShowExplanation(true);
  }

  function toggleOption(optionIndex: number) {
    if (isSubmitted) return;
    const value = String(optionIndex);
    const nextSelected = selected.includes(value) ? selected.filter(item => item !== value) : [...selected, value];
    setSelected(nextSelected);
    if (current && !isMultiQuestion(current) && nextSelected.length === 1) {
      void handleSubmit(nextSelected);
    }
  }

  function updateSubAnswer(subQuestionId: string, patch: Partial<LocalSubAnswer>) {
    setSubAnswerById(prev => {
      const currentState = prev[subQuestionId] || { selectedOptions: [], answerText: '' };
      return {
        ...prev,
        [subQuestionId]: {
          ...currentState,
          ...patch,
        },
      };
    });
  }

  function toggleSubOption(subQuestion: Record<string, unknown>, subQuestionIndex: number, optionIndex: number) {
    if (isSubmitted) return;
    const id = subQuestionId(subQuestion, subQuestionIndex);
    const value = String(optionIndex);
    const currentState = subAnswerById[id] || { selectedOptions: [], answerText: '' };
    const nextSelected = currentState.selectedOptions.includes(value)
      ? currentState.selectedOptions.filter(item => item !== value)
      : isMultiSubQuestion(subQuestion)
        ? [...currentState.selectedOptions, value]
        : [value];
    updateSubAnswer(id, { selectedOptions: nextSelected });
  }

  function buildSubAnswers() {
    return subQuestions
      .map((subQuestion, subQuestionIndex) => {
        const id = subQuestionId(subQuestion, subQuestionIndex);
        const state = subAnswerById[id] || { selectedOptions: [], answerText: '' };
        const objective = isObjectiveSubQuestion(subQuestion);
        return {
          subQuestionId: id,
          selectedOptions: objective ? state.selectedOptions : [],
          answerText: objective ? '' : state.answerText,
          selfJudgedCorrect: objective ? undefined : state.selfJudgedCorrect,
        };
      })
      .filter(item => item.selectedOptions.length || item.answerText.trim() || item.selfJudgedCorrect !== undefined);
  }

  async function handleSubmit(nextSelected = selected, selfCorrect?: boolean) {
    if (!session || !current) return;
    if (hasCompositeSubQuestions) {
      try {
        const subAnswers = buildSubAnswers();
        if (!subAnswers.length) {
          setError('请至少完成一个子题后再提交。');
          return;
        }
        const payload = await submitAnswer({
          practiceSessionId: session.id,
          questionId: current.id,
          subAnswers,
        });
        rememberAnswer(current.id, payload.item, [], '');
      } catch (nextError) {
        setError(nextError instanceof Error ? nextError.message : '提交失败');
      }
      return;
    }
    if (!isObjectiveQuestion(current) && selfCorrect !== undefined) {
      try {
        const payload = await submitAnswer({
          practiceSessionId: session.id,
          questionId: current.id,
          selectedOptions: [],
          answerText,
          selfJudgedCorrect: selfCorrect,
        });
        rememberAnswer(current.id, payload.item);
      } catch (nextError) {
        setError(nextError instanceof Error ? nextError.message : '提交失败');
      }
      return;
    }
    try {
      const payload = await submitAnswer({
        practiceSessionId: session.id,
        questionId: current.id,
        selectedOptions: nextSelected,
        answerText,
      });
      rememberAnswer(current.id, payload.item, nextSelected);
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '提交失败');
    }
  }

  function previousQuestion() {
    setIndex(prev => Math.max(0, prev - 1));
    setCompleted(false);
  }

  function nextQuestion() {
    if (index >= questions.length - 1) {
      setCompleted(true);
      return;
    }
    setIndex(prev => Math.min(questions.length - 1, prev + 1));
    setCompleted(false);
  }

  function jumpQuestion(nextIndex: number) {
    setIndex(Math.max(0, Math.min(questions.length - 1, nextIndex)));
    setCompleted(false);
  }

  async function handleFavorite() {
    if (!current) return;
    const nextFavorite = !favoriteByQuestion[current.id];
    await toggleQuestionFavorite(current.id, nextFavorite)
      .then(payload => {
        setFavoriteByQuestion(prev => ({ ...prev, [current.id]: payload.favorite }));
        Taro.showToast({ title: payload.favorite ? '已收藏' : '已取消', icon: 'success' });
      })
      .catch(nextError => setError(nextError instanceof Error ? nextError.message : '收藏失败'));
  }

  async function handleFeedback() {
    if (!current || !feedbackText.trim()) {
      setError('请先填写反馈内容。');
      return;
    }
    try {
      await submitFeedback({
        questionId: current.id,
        type: 'question_error',
        title: '题目反馈',
        description: feedbackText.trim(),
        priority: 'normal',
      });
      setFeedbackText('');
      Taro.showToast({ title: '已提交反馈', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '反馈提交失败');
    }
  }

  async function handleSubmitSession(auto = false) {
    if (!session) return;
    if (!auto) {
      const ok = await Taro.showModal({
        title: '交卷',
        content: `已答 ${answeredCount}/${questions.length}，确认交卷并生成练习报告？`,
        confirmText: '交卷',
        cancelText: '取消',
      });
      if (!ok.confirm) return;
    }
    try {
      const payload = await submitPracticeSession(session.id);
      setReport(payload.item || null);
      setCompleted(true);
      Taro.showToast({ title: '报告已生成', icon: 'success' });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : '交卷失败');
    }
  }

  function openReport() {
    if (!session) return;
    Taro.navigateTo({ url: `/pages/student/reports/index?practiceSessionId=${session.id}` });
  }

  function openVideo() {
    if (!current) return;
    Taro.navigateTo({ url: `/pages/student/video/index?questionId=${current.id}` });
  }

  function subResultFor(subQuestion: Record<string, unknown>, subQuestionIndex: number) {
    const id = subQuestionId(subQuestion, subQuestionIndex);
    return (answerState?.subResults || []).find(item => item.subQuestionId === id);
  }

  return (
    <View className='student-page'>
      <View className='student-topbar'>
        <View className='student-title-block'>
          <Text className='student-kicker'>{session ? `${index + 1}/${questions.length || session.questionCount}` : 'Practice'}</Text>
          <Text className='student-title'>{session?.mode || '练习'}</Text>
          <Text className='student-subtitle'>题目来自后端 session 快照，答题、交卷、错题和报告都以后端校验为准。</Text>
        </View>
        {timeLeft !== null ? <Text className='status-badge'>{formatDuration(timeLeft)}</Text> : null}
      </View>

      {session ? (
        <View className='quiet-panel section-block'>
          <View className='amount-row'>
            <Text className='row-main'>进度 {answeredCount}/{questions.length}</Text>
            <Text className='status-badge'>{progressPercent}%</Text>
          </View>
          <Text className='row-meta'>正确 {correctCount} · 错误 {wrongCount} · 未答 {Math.max(0, questions.length - answeredCount)} · {session.accessMode || 'access'}</Text>
          {session.consumedFreeQuota ? <Text className='row-meta'>本次消耗免费题量 {session.consumedFreeQuota}</Text> : null}
        </View>
      ) : null}

      {report ? (
        <View className='report-panel section-block'>
          <Text className='metric-value'>{String(report.score)} / {String(report.totalScore)}</Text>
          <Text className='metric-label'>正确率 {Math.round((report.accuracy || 0) * 100)}% · 已答 {report.answeredCount}/{report.totalQuestions}</Text>
          <View className='toolbar'>
            <Button className='primary-button' onClick={openReport}>查看报告</Button>
          </View>
        </View>
      ) : null}

      {completed && !report ? (
        <View className='report-panel section-block'>
          <Text className='metric-value'>已完成本组练习</Text>
          <Text className='metric-label'>已答 {answeredCount}/{questions.length} · 正确 {correctCount} · 错误 {wrongCount}</Text>
          <View className='toolbar wrap'>
            <Button className='primary-button' onClick={() => handleSubmitSession()}>生成报告</Button>
            <Button className='secondary-button' onClick={() => jumpQuestion(0)}>重新查看</Button>
            <Button className='secondary-button' onClick={() => Taro.navigateTo({ url: '/pages/student/review/index?type=wrong' })}>查看错题</Button>
          </View>
        </View>
      ) : null}

      {loading ? <View className='empty-state'>练习加载中...</View> : null}

      {current && !completed ? (
        <View className='list-stack'>
          <View className='quiet-panel'>
            <View className='amount-row'>
              <Text className='row-meta'>{current.typeLabel || current.type || '题目'}</Text>
              <Text className='status-badge'>{answerLabel(answerState)}</Text>
            </View>
            <RichContent content={current.content || '未提供题干'} mediaUrls={[current.mediaUrl]} />
            {hasCompositeSubQuestions ? <Text className='row-meta'>包含 {subQuestions.length} 个子题，请结合题干作答。</Text> : null}
          </View>
          {hasCompositeSubQuestions ? (
            <View className='list-stack'>
              {subQuestions.map((subQuestion, subQuestionIndex) => {
                const id = subQuestionId(subQuestion, subQuestionIndex);
                const localAnswer = subAnswerById[id] || { selectedOptions: [], answerText: '' };
                const objective = isObjectiveSubQuestion(subQuestion);
                const subOptions = subQuestionOptions(subQuestion);
                const result = subResultFor(subQuestion, subQuestionIndex);
                return (
                  <View className='quiet-panel composite-subquestion' key={id}>
                    <View className='amount-row'>
                      <Text className='row-meta'>第 {subQuestionIndex + 1} 小题 · {String(subQuestion.typeLabel || subQuestion.type || '子题')}</Text>
                      {result ? <Text className='status-badge'>{result.isCorrect === true ? '正确' : result.isCorrect === false ? '错误' : '已答'}</Text> : null}
                    </View>
                    <RichContent content={String(subQuestion.content || '未提供子题题干')} compact />
                    {objective ? (
                      <View className='sub-option-list'>
                        {subOptions.map((option, optionIndex) => (
                          <View
                            className={`list-row ${localAnswer.selectedOptions.includes(String(optionIndex)) ? 'active' : ''}`}
                            key={`${id}-${optionIndex}`}
                            onClick={() => toggleSubOption(subQuestion, subQuestionIndex, optionIndex)}
                          >
                            <View className='option-line'>
                              <Text className='option-prefix'>{String.fromCharCode(65 + optionIndex)}.</Text>
                              <RichContent className='option-rich' content={plainOption(option, optionIndex)} compact />
                            </View>
                          </View>
                        ))}
                      </View>
                    ) : (
                      <View>
                        <Textarea
                          className='textarea'
                          placeholder='请输入本小题答案，查看参考答案后可自评。'
                          value={localAnswer.answerText}
                          disabled={isSubmitted}
                          onInput={event => updateSubAnswer(id, { answerText: String(event.detail.value || '') })}
                        />
                        {!isSubmitted ? (
                          <View className='toolbar wrap'>
                            <Button className={localAnswer.selfJudgedCorrect === true ? 'pill-button active' : 'pill-button'} onClick={() => updateSubAnswer(id, { selfJudgedCorrect: true })}>答对了</Button>
                            <Button className={localAnswer.selfJudgedCorrect === false ? 'pill-button warn' : 'pill-button'} onClick={() => updateSubAnswer(id, { selfJudgedCorrect: false })}>答错了</Button>
                          </View>
                        ) : null}
                      </View>
                    )}
                    {showExplanation || isSubmitted ? (
                      <View className='sub-explanation'>
                        {result?.correctOptionIndices?.length ? <Text className='row-meta'>正确选项：{result.correctOptionIndices.map(item => String.fromCharCode(65 + item)).join('、')}</Text> : null}
                        {result?.correctOptionIndex !== null && result?.correctOptionIndex !== undefined ? <Text className='row-meta'>正确选项：{String.fromCharCode(65 + result.correctOptionIndex)}</Text> : null}
                        {result?.correctAnswerText ? (
                          <View className='answer-detail'>
                            <Text className='answer-detail-label'>参考答案</Text>
                            <RichContent content={result.correctAnswerText} compact muted />
                          </View>
                        ) : null}
                        {result?.explanation ? (
                          <View className='answer-detail'>
                            <Text className='answer-detail-label'>解析</Text>
                            <RichContent content={result.explanation} compact muted />
                          </View>
                        ) : null}
                      </View>
                    ) : null}
                  </View>
                );
              })}
            </View>
          ) : options.length ? options.map((option, optionIndex) => (
            <View
              className={`list-row ${selected.includes(String(optionIndex)) ? 'active' : ''}`}
              key={String(optionIndex)}
              onClick={() => toggleOption(optionIndex)}
            >
              <View className='option-line'>
                <Text className='option-prefix'>{String.fromCharCode(65 + optionIndex)}.</Text>
                <RichContent className='option-rich' content={plainOption(option, optionIndex)} compact />
              </View>
            </View>
          )) : (
            <View className='quiet-panel'>
              <Textarea className='textarea' placeholder='请输入答案或先思考后查看参考答案' value={answerText} onInput={event => setAnswerText(String(event.detail.value || ''))} />
              <View className='toolbar wrap'>
                <Button className='secondary-button' onClick={() => setShowExplanation(true)}>查看答案</Button>
                <Button className='primary-button' onClick={() => handleSubmit(selected, true)}>答对了</Button>
                <Button className='danger-button' onClick={() => handleSubmit(selected, false)}>答错了</Button>
              </View>
            </View>
          )}
          {showExplanation || isSubmitted ? (
            <View className='quiet-panel'>
              {isSubmitted ? <Text className={answerState?.isCorrect ? 'success-text' : answerState?.isCorrect === false ? 'error-text' : 'row-meta'}>{answerLabel(answerState)}</Text> : null}
              {answerState?.subResults?.length ? <Text className='row-meta'>子题正确 {answerState.subResults.filter(item => item.isCorrect === true).length}/{answerState.subResults.length}</Text> : null}
              {current.answerText ? (
                <View className='answer-detail'>
                  <Text className='answer-detail-label'>参考答案</Text>
                  <RichContent content={current.answerText} compact />
                </View>
              ) : null}
              {current.correctOptionIndices?.length ? <Text className='row-meta'>正确选项：{current.correctOptionIndices.map(item => String.fromCharCode(65 + item)).join('、')}</Text> : null}
              {current.correctOptionIndex !== null && current.correctOptionIndex !== undefined ? <Text className='row-meta'>正确选项：{String.fromCharCode(65 + current.correctOptionIndex)}</Text> : null}
              {current.explanation ? (
                <View className='answer-detail'>
                  <Text className='answer-detail-label'>解析</Text>
                  <RichContent content={current.explanation} compact muted />
                </View>
              ) : null}
            </View>
          ) : null}
          <View className='toolbar wrap'>
            {isObjectiveQuestion(current) || hasCompositeSubQuestions ? <Button className='primary-button' onClick={() => handleSubmit()}>提交</Button> : null}
            <Button className='secondary-button' onClick={previousQuestion}>上一题</Button>
            <Button className='secondary-button' onClick={handleFavorite}>{favoriteByQuestion[current.id] ? '取消收藏' : '收藏'}</Button>
            {current.hasVideoExplanation ? <Button className='secondary-button' onClick={openVideo}>视频</Button> : null}
            <Button className='secondary-button' onClick={nextQuestion}>下一题</Button>
            <Button className='secondary-button' onClick={() => handleSubmitSession()}>交卷</Button>
          </View>
          <View className='quiet-panel'>
            <Text className='row-main'>题目反馈</Text>
            <Textarea className='textarea' placeholder='题干、答案、解析或视频存在问题，可以在这里提交给后台处理。' value={feedbackText} onInput={event => setFeedbackText(String(event.detail.value || ''))} />
            <View className='toolbar'>
              <Button className='secondary-button' onClick={handleFeedback}>提交反馈</Button>
            </View>
          </View>
        </View>
      ) : !loading && !completed ? <View className='empty-state'>暂无题目。请确认后台已发布题目并配置集合或练习蓝图。</View> : null}

      {questions.length ? (
        <View className='section-block'>
          <Text className='section-heading'>答题卡</Text>
          <View className='answer-sheet'>
            {questions.map((item, cardIndex) => (
              <Button
                key={item.id}
                className={`answer-card ${cardIndex === index ? 'current' : ''} ${answerByQuestion[item.id] ? 'answered' : ''} ${answerByQuestion[item.id]?.isCorrect === false ? 'wrong' : ''}`}
                onClick={() => jumpQuestion(cardIndex)}
              >
                {cardIndex + 1}
              </Button>
            ))}
          </View>
        </View>
      ) : null}
      {error ? <Text className='error-text'>{error}</Text> : null}
    </View>
  );
}
