<script setup lang="ts">
import { useRouter } from 'vue-router'
import LoadIcon from '@/page/system/mailbox/components/LoadIcon.vue'
import wrongQuestionApi, {
  type WrongQuestionItem,
  type FilterSubject,
  type FilterTextbook,
  type FilterChapter,
} from '@/api/subject/wrongQuestion'
import { debounce, TypeSet } from '@/hooks'
import { resource_type_wrong_retry, resource_type_similar_recommend } from '@/page/subject/doWork'

defineOptions({ name: 'HomeWorkWrongQuestion' })

const router = useRouter()

const list = ref<WrongQuestionItem[]>([])
const page = reactive({
  current: 1,
  size: 10,
  total: 0,
})
const loading = ref(false)
const pageLoading = ref(false)
const emptyText = ref('暂无错题')

// ---- 时间范围 ----
const timeRangeOptions = [
  { value: '', label: '全部时间' },
  { value: 'today', label: '今天' },
  { value: '7days', label: '近7天' },
  { value: '30days', label: '近30天' },
]

function getTimeRange(rangeKey: string): { startTime?: string; endTime?: string } {
  if (!rangeKey) return {}
  const now = new Date()
  const endTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} 23:59:59`
  let start: Date
  if (rangeKey === 'today') {
    start = now
  } else if (rangeKey === '7days') {
    start = new Date(now.getTime() - 6 * 86400000)
  } else {
    start = new Date(now.getTime() - 29 * 86400000)
  }
  const startTime = `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')} 00:00:00`
  return { startTime, endTime }
}

// ---- 筛选 ----
const filterSubjects = ref<FilterSubject[]>([])
const filterForm = reactive({
  subjectId: '' as string | number,
  timeRange: '',
})

const subjectSelectList = computed(() => [
  { value: '', label: '全部学科' },
  ...filterSubjects.value.map((s: FilterSubject) => ({ value: s.id, label: s.name })),
])

async function getFilterSubjects() {
  try {
    const res = await wrongQuestionApi.getFilterSubjects()
    filterSubjects.value = res || []
    if (filterSubjects.value.length === 1) {
      filterForm.subjectId = filterSubjects.value[0].id
    }
  } catch {}
}

function handleFilterChange() {
  initList()
}

function handleSubjectChange() {
  initList()
}

function getPreviewHtml(item: WrongQuestionItem): string {
  if (!item.questionTitle) return '--'
  const html = item.questionTitle.stemHtml || item.questionTitle.stem || ''
  if (!html) return '--'
  return String(html).replace(/http:\/\//gi, 'https://')
}

// ---- 做题记录弹框 ----
const showRecordDia = ref(false)

function openRecordDia() {
  showRecordDia.value = true
}

function goHistory(resourceType: number) {
  showRecordDia.value = false
  router.push({ path: '/system/homeWork/history', query: { resourceType: String(resourceType) } })
}

const expandedIds = ref(new Set<number>())
function toggleExpand(id: number) {
  const s = new Set(expandedIds.value)
  const expanding = !s.has(id)
  expanding ? s.add(id) : s.delete(id)
  expandedIds.value = s
  if (expanding) {
    nextTick(() => {
      TypeSet([document.querySelector(`.expand-section-${id}`)])
    })
  }
}

function parseOptions(optionHtml: string | undefined): { index: string; html: string }[] | null {
  if (!optionHtml) return null
  try {
    const parsed = typeof optionHtml === 'string' ? JSON.parse(optionHtml) : optionHtml
    if (Array.isArray(parsed)) {
      return parsed.map((item: any) => ({
        index: item.index || '',
        html: item.html || '',
      }))
    }
  } catch {
    /* not JSON, fallback */
  }
  return null
}

async function getList() {
  const { startTime, endTime } = getTimeRange(filterForm.timeRange)
  const res = await wrongQuestionApi.getList({
    current: page.current,
    size: page.size,
    subjectId: filterForm.subjectId ? Number(filterForm.subjectId) : undefined,
    startTime,
    endTime,
  })
  list.value.push(...(res.rows || []))
  page.total = res.totalRows
}

async function initList() {
  if (pageLoading.value) return
  pageLoading.value = true
  list.value = []
  page.current = 1
  expandedIds.value = new Set()
  try {
    await getList()
    emptyText.value = list.value.length ? '' : '暂无错题'
  } catch {
    emptyText.value = '网络出问题了啦～'
  }
  pageLoading.value = false
}

const scrollBoxRef = ref()
async function handleScroll(event: any) {
  if (list.value.length >= page.total) return
  if (loading.value) return
  if (event.target.scrollTop + event.target.offsetHeight >= scrollBoxRef.value?.offsetHeight - 50) {
    page.current++
    try {
      loading.value = true
      await getList()
    } catch {
      page.current--
    }
    loading.value = false
  }
}

const debounceScroll = debounce(handleScroll, 200, false)

const formatTime = (time: string) => {
  if (!time) return '--'
  return time.replace('T', ' ').slice(0, 16)
}

// ---- 错题重练弹框 ----
const showRetryDia = ref(false)
const retryForm = reactive({
  subjectId: '' as string | number,
  textbookId: '' as string | number,
  chapterId: '' as string | number,
  questionCount: 3,
  timeRange: '',
})

const retrySubjectSelectList = computed(() => {
  const items = filterSubjects.value.map((s: FilterSubject) => ({ value: s.id, label: s.name }))
  if (items.length === 1) return items
  return [{ value: '', label: '全部学科' }, ...items]
})

const retryTextbooks = ref<FilterTextbook[]>([])
const retryTextbookSelectList = computed(() => [
  { value: '', label: '全部教材' },
  ...retryTextbooks.value.map((t: FilterTextbook) => ({ value: t.id, label: t.name })),
])

const retryChapters = ref<FilterChapter[]>([])
type RetryChapterNode = FilterChapter & { children?: RetryChapterNode[] }
const chapterTreeOpen = ref(false)

function isRootChapter(parentId: unknown) {
  return (
    parentId === 0 ||
    parentId === '0' ||
    parentId === '' ||
    parentId === null ||
    parentId === undefined
  )
}

function normalizeChapterTree(chapters: any[]): RetryChapterNode[] {
  return chapters.map((chapter: any) => {
    const node: RetryChapterNode = {
      ...chapter,
    }
    if (Array.isArray(chapter.children) && chapter.children.length) {
      node.children = normalizeChapterTree(chapter.children)
    } else {
      delete node.children
    }
    return node
  })
}

function getParentId(chapter: any): unknown {
  return chapter.parentId ?? chapter.pid ?? chapter.parent_id
}

function buildChapterTree(chapters: FilterChapter[]): RetryChapterNode[] {
  if (!chapters.length) return []
  const hasTreeData = chapters.some(
    (chapter: any) => Array.isArray(chapter.children) && chapter.children.length > 0,
  )
  if (hasTreeData) return normalizeChapterTree(chapters as any[])

  const chapterMap = new Map<number, RetryChapterNode>()
  const roots: RetryChapterNode[] = []

  for (const chapter of chapters) {
    chapterMap.set(Number(chapter.id), { ...chapter, children: [] })
  }

  for (const chapter of chapters) {
    const node = chapterMap.get(Number(chapter.id))!
    const pId = getParentId(chapter)
    if (isRootChapter(pId)) {
      roots.push(node)
      continue
    }
    const parentNode = chapterMap.get(Number(pId))
    if (parentNode) {
      parentNode.children!.push(node)
    } else {
      roots.push(node)
    }
  }

  const clearEmptyChildren = (items: RetryChapterNode[]) => {
    items.forEach(item => {
      if (!item.children?.length) {
        delete item.children
      } else {
        clearEmptyChildren(item.children)
      }
    })
  }
  clearEmptyChildren(roots)
  return roots
}

const retryChapterTree = computed(() => buildChapterTree(retryChapters.value))
const defaultExpandedKeys = computed(() => retryChapterTree.value.map(n => n.id))

function findChapterById(
  chapters: RetryChapterNode[],
  chapterId: string | number,
): RetryChapterNode | undefined {
  for (const chapter of chapters) {
    if (String(chapter.id) === String(chapterId)) return chapter
    if (chapter.children?.length) {
      const matched = findChapterById(chapter.children, chapterId)
      if (matched) return matched
    }
  }
  return undefined
}

const selectedRetryChapterLabel = computed(() => {
  if (!retryForm.chapterId && retryForm.chapterId !== 0) return '全部章节'
  const chapter = findChapterById(retryChapterTree.value, retryForm.chapterId)
  return chapter?.name || '全部章节'
})

function toggleChapterTree() {
  chapterTreeOpen.value = !chapterTreeOpen.value
}

function closeChapterTree() {
  chapterTreeOpen.value = false
}

function selectAllChapters() {
  retryForm.chapterId = ''
  closeChapterTree()
}

function handleChapterNodeClick(chapter: RetryChapterNode) {
  if (chapter.children?.length) return
  retryForm.chapterId = chapter.id
  closeChapterTree()
}

function isChapterActive(chapterId: number) {
  return String(retryForm.chapterId) === String(chapterId)
}

async function loadRetryChapters(textbookId: number) {
  try {
    retryChapters.value =
      (await wrongQuestionApi.getTextbookCatalogList({
        textbookId,
        size: -1,
      })) || []
  } catch {
    retryChapters.value = []
  }
}

async function loadRetryTextbooks(subjectId: number) {
  try {
    retryTextbooks.value = (await wrongQuestionApi.getFilterTextbooks({ subjectId })) || []
    if (retryTextbooks.value.length) {
      retryForm.textbookId = retryTextbooks.value[0].id
      await loadRetryChapters(Number(retryForm.textbookId))
    }
  } catch {
    retryTextbooks.value = []
    retryChapters.value = []
  }
}

function handleRetrySubjectChange() {
  retryForm.textbookId = ''
  retryForm.chapterId = ''
  closeChapterTree()
  retryTextbooks.value = []
  retryChapters.value = []
  if (retryForm.subjectId) {
    loadRetryTextbooks(Number(retryForm.subjectId))
  }
}

function handleRetryTextbookChange() {
  retryForm.chapterId = ''
  closeChapterTree()
  retryChapters.value = []
  if (retryForm.textbookId) {
    loadRetryChapters(Number(retryForm.textbookId))
  }
}

function openRetryDia() {
  retryForm.textbookId = ''
  retryForm.chapterId = ''
  retryForm.questionCount = 3
  retryForm.timeRange = ''
  closeChapterTree()
  retryTextbooks.value = []
  retryChapters.value = []
  if (filterSubjects.value.length === 1) {
    retryForm.subjectId = filterSubjects.value[0].id
    loadRetryTextbooks(filterSubjects.value[0].id)
  } else {
    retryForm.subjectId = ''
  }
  showRetryDia.value = true
}

function changeCount(delta: number) {
  const v = retryForm.questionCount + delta
  if (v >= 1 && v <= 50) retryForm.questionCount = v
}

function handleRetryOK() {
  const { startTime, endTime } = getTimeRange(retryForm.timeRange)
  const query: Record<string, any> = {
    resourceType: resource_type_wrong_retry,
    questionCount: retryForm.questionCount,
  }
  if (retryForm.subjectId) query.subjectId = retryForm.subjectId
  if (retryForm.textbookId) query.textbookId = retryForm.textbookId
  if (retryForm.chapterId) query.chapterId = retryForm.chapterId
  if (startTime) query.startTime = startTime
  if (endTime) query.endTime = endTime

  router.push({ path: '/subject/doWork', query })
}

function handleSimilarRecommend(item: WrongQuestionItem) {
  router.push({
    path: '/subject/doWork',
    query: {
      resourceType: resource_type_similar_recommend,
      questionId: item.questionId,
    },
  })
}

onActivated(async () => {
  pageLoading.value = false
  loading.value = false
  showRetryDia.value = false
  showRecordDia.value = false
  closeChapterTree()
  await getFilterSubjects()
  initList()
})

const handleGlobalSelectOpen = () => {
  closeChapterTree()
}

onMounted(() => {
  window.addEventListener('xuexiaole-select-open', handleGlobalSelectOpen as EventListener)
})

onUnmounted(() => {
  window.removeEventListener('xuexiaole-select-open', handleGlobalSelectOpen as EventListener)
})
</script>

<template>
  <div class="wrong-question">
    <div class="top">
      <BackBar leftText="错题本" />
      <div class="top-filters">
        <Select
          v-model="filterForm.subjectId"
          :selectList="subjectSelectList"
          @selectChange="handleSubjectChange"
        />
        <Select
          v-model="filterForm.timeRange"
          :selectList="timeRangeOptions"
          @selectChange="handleFilterChange"
        />
      </div>
      <div class="top-right">
        <mj-button tilt @click="openRecordDia">做题记录</mj-button>
        <mj-button type="success" tilt @click="openRetryDia">错题重练</mj-button>
      </div>
    </div>

    <div class="main">
      <div class="main-header">
        <div class="header-cell flex-3">题目预览</div>
        <div class="header-cell flex-1">错误次数</div>
        <div class="header-cell flex-2">首次错误时间</div>
        <div class="header-cell flex-2">最近错误时间</div>
        <div class="header-cell flex-1">操作</div>
        <div class="header-cell flex-05"></div>
      </div>
      <div class="main-body">
        <template v-if="list.length">
          <div class="main-list hidden_scroll" @scroll="debounceScroll">
            <div ref="scrollBoxRef" class="scroll-box">
              <div v-for="item in list" :key="item.id" class="list-item-wrapper">
                <div class="list-item pointer" @click="toggleExpand(item.id)">
                  <div class="item-cell flex-3 preview-cell">
                    <div class="question-preview html-content" v-html="getPreviewHtml(item)"></div>
                  </div>
                  <div class="item-cell flex-1">
                    <span class="error-count">{{ item.errorCount }}</span>
                  </div>
                  <div class="item-cell flex-2 time-cell">
                    {{ formatTime(item.firstErrorTime) }}
                  </div>
                  <div class="item-cell flex-2 time-cell">
                    {{ formatTime(item.lastErrorTime) }}
                  </div>
                  <div class="item-cell flex-1">
                    <span class="similar-btn pointer" @click.stop="handleSimilarRecommend(item)"
                      >举一反三</span
                    >
                  </div>
                  <div class="item-cell flex-05">
                    <span class="expand-arrow" :class="{ expanded: expandedIds.has(item.id) }"
                      >▼</span
                    >
                  </div>
                </div>

                <div
                  v-if="expandedIds.has(item.id) && item.questionTitle"
                  :class="['expand-section', `expand-section-${item.id}`]"
                >
                  <div class="expand-grid">
                    <div v-if="item.questionTitle.typeName" class="expand-item">
                      <span class="expand-label">题型</span>
                      <span class="expand-value">{{ item.questionTitle.typeName }}</span>
                    </div>
                    <div v-if="item.questionTitle.difficultyLevel" class="expand-item">
                      <span class="expand-label">难度</span>
                      <span class="expand-value">{{ item.questionTitle.difficultyLevel }}</span>
                    </div>
                    <div v-if="item.questionTitle.score" class="expand-item">
                      <span class="expand-label">分值</span>
                      <span class="expand-value">{{ item.questionTitle.score }}分</span>
                    </div>
                    <div v-if="item.questionTitle.submitAnswer" class="expand-item">
                      <span class="expand-label">提交答案</span>
                      <span class="expand-value submit-answer">{{
                        item.questionTitle.submitAnswer
                      }}</span>
                    </div>
                    <div
                      v-if="item.questionTitle.stemHtml || item.questionTitle.stem"
                      class="expand-item full"
                    >
                      <span class="expand-label">题干</span>
                      <div
                        class="expand-value html-content"
                        v-html="item.questionTitle.stemHtml || item.questionTitle.stem"
                      ></div>
                    </div>
                    <div v-if="item.questionTitle.optionHtml" class="expand-item full">
                      <span class="expand-label">选项</span>
                      <div class="expand-value html-content">
                        <template v-if="parseOptions(item.questionTitle.optionHtml)">
                          <div
                            v-for="opt in parseOptions(item.questionTitle.optionHtml)"
                            :key="opt.index"
                            class="option-item"
                          >
                            <span class="option-index">{{ opt.index }}.</span>
                            <span class="option-html" v-html="opt.html"></span>
                          </div>
                        </template>
                        <div v-else v-html="item.questionTitle.optionHtml"></div>
                      </div>
                    </div>
                    <div
                      v-if="item.questionTitle.answerHtml || item.questionTitle.answer"
                      class="expand-item full"
                    >
                      <span class="expand-label">正确答案</span>
                      <div
                        class="expand-value html-content answer-text"
                        v-html="item.questionTitle.answerHtml || item.questionTitle.answer"
                      ></div>
                    </div>
                    <div v-if="item.questionTitle.explanation" class="expand-item full">
                      <span class="expand-label">解析</span>
                      <div
                        class="expand-value html-content"
                        v-html="item.questionTitle.explanation"
                      ></div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <LoadIcon v-if="loading" class="load-icon" />
        </template>
        <Empty
          v-else
          class="empty"
          :type="pageLoading ? 'loading' : 'learn'"
          :content="emptyText"
        />
      </div>
    </div>

    <mj-dialog
      v-model="showRetryDia"
      ok-text="开始重练"
      title="错题重练"
      :width="960"
      :ok="handleRetryOK"
    >
      <div class="retry-body">
        <div class="retry-body-title">系统将从您的错题本中随机抽取题目进行重练</div>
        <div class="retry-form">
          <div class="retry-form-row">
            <div class="retry-form-item">
              <label>学科</label>
              <Select
                v-model="retryForm.subjectId"
                :selectList="retrySubjectSelectList"
                @selectChange="handleRetrySubjectChange"
              />
            </div>
            <div class="retry-form-item">
              <label>教材</label>
              <Select
                v-model="retryForm.textbookId"
                :selectList="retryTextbookSelectList"
                @selectChange="handleRetryTextbookChange"
              />
            </div>
            <div class="retry-form-item">
              <label>章节</label>
              <div :class="['chapter-tree-select', { open: chapterTreeOpen }]">
                <div class="chapter-tree-trigger" @click.stop="toggleChapterTree">
                  <span>{{ selectedRetryChapterLabel }}</span>
                  <span :class="['chapter-tree-arrow', { open: chapterTreeOpen }]">⌃</span>
                </div>
                <div v-show="chapterTreeOpen" class="chapter-tree-panel" @click.stop>
                  <div
                    :class="['chapter-tree-all', { active: !retryForm.chapterId }]"
                    @click="selectAllChapters"
                  >
                    全部章节
                  </div>
                  <el-tree
                    v-if="retryChapterTree.length"
                    class="chapter-tree"
                    node-key="id"
                    :data="retryChapterTree"
                    :props="{ label: 'name', children: 'children' }"
                    :expand-on-click-node="true"
                    :highlight-current="true"
                    :default-expanded-keys="defaultExpandedKeys"
                    :current-node-key="
                      retryForm.chapterId ? Number(retryForm.chapterId) : undefined
                    "
                    @node-click="handleChapterNodeClick"
                  >
                    <template #default="{ data }">
                      <span :class="['chapter-node-label', { active: isChapterActive(data.id) }]">
                        {{ data.name }}
                      </span>
                    </template>
                  </el-tree>
                  <div v-else class="chapter-tree-empty">暂无章节</div>
                </div>
                <div
                  v-show="chapterTreeOpen"
                  class="chapter-tree-mask"
                  @click="closeChapterTree"
                ></div>
              </div>
            </div>
            <div class="retry-form-item">
              <label>时间</label>
              <Select v-model="retryForm.timeRange" :selectList="timeRangeOptions" />
            </div>
          </div>
          <div class="retry-form-count">
            <label>抽取题目数量</label>
            <div class="count-control">
              <span class="count-btn pointer" @click="changeCount(-1)">－</span>
              <input
                v-model.number="retryForm.questionCount"
                type="number"
                min="1"
                max="50"
                class="count-input"
              />
              <span class="count-btn pointer" @click="changeCount(1)">＋</span>
            </div>
            <span class="count-hint">（1-50题）</span>
          </div>
        </div>
      </div>
    </mj-dialog>

    <mj-dialog v-model="showRecordDia" title="做题记录" :width="600" :hideFooter="true">
      <div class="record-body">
        <div class="record-option pointer" @click="goHistory(1)">
          <span class="record-option-icon">📝</span>
          <span class="record-option-text">错题重练记录</span>
          <span class="record-option-arrow">▶</span>
        </div>
        <div class="record-option pointer" @click="goHistory(2)">
          <span class="record-option-icon">🔄</span>
          <span class="record-option-text">举一反三记录</span>
          <span class="record-option-arrow">▶</span>
        </div>
      </div>
    </mj-dialog>
  </div>
</template>

<style scoped lang="scss">
.wrong-question {
  @include main_bg;
  position: relative;
  width: 100vw;
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;
  line-height: 1.5;

  .top {
    width: 100%;
    padding: 2.67vh 64px 0;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    display: flex;
    align-items: center;

    &-filters {
      display: flex;
      align-items: center;
      gap: 1.5vh;
      margin-left: 3vh;
    }

    &-right {
      flex-shrink: 0;
      display: flex;
      gap: 1.5vh;
      margin-left: auto;

      .mj-button {
        font-family: $font-text;
      }
    }
  }

  .main {
    position: relative;
    margin: 11.33vh auto 0;
    width: 1792px;
    height: 86vh;
    border-radius: 1.67vh;
    overflow: hidden;

    &-header {
      display: flex;
      align-items: center;
      height: 7vh;
      background: linear-gradient(269deg, #86e6ff 2.25%, #9effda 51.93%, #5fdcfd 99.65%);
      padding: 0 3vh;
      border-radius: 1.67vh 1.67vh 0 0;

      .header-cell {
        font-family: $font-special;
        font-size: 2.33vh;
        color: $font-color;
        font-weight: 600;
        text-align: center;
      }
    }

    &-body {
      height: calc(100% - 7vh);
      background: linear-gradient(180deg, #f0faff 0%, #fafdff 100%);
      border-radius: 0 0 1.67vh 1.67vh;
      padding: 1.5vh 0;
    }

    &-list {
      height: 100%;
      padding: 0 1vh;
    }

    .empty {
      height: 70vh;
    }

    .load-icon {
      position: absolute;
      bottom: 3vh;
      left: 50%;
      transform: translateX(-50%);
    }
  }

  .flex-05 {
    flex: 0.5;
  }

  .flex-1 {
    flex: 1;
  }

  .flex-2 {
    flex: 2;
  }

  .flex-3 {
    flex: 3;
  }

  .list-item-wrapper {
    margin: 0 1vh 1vh;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 1.33vh;
    box-shadow: 0 0.17vh 0.33vh rgba(0, 0, 0, 0.06);
    transition: box-shadow 0.2s;
    overflow: hidden;

    &:hover {
      box-shadow: 0 0.33vh 0.67vh rgba(0, 0, 0, 0.1);
    }
  }

  .list-item {
    display: flex;
    align-items: center;
    padding: 2vh 3vh;

    .item-cell {
      text-align: center;
      font-size: 2.17vh;
      font-family: $font-text;
      color: #333;
    }

    .preview-cell {
      text-align: left !important;
    }

    .question-preview {
      color: #333;
      font-size: 2vh;
      line-height: 1.5;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
      text-overflow: ellipsis;
      word-break: break-all;

      :deep(p) {
        margin: 0;
      }

      :deep(img) {
        max-width: 100%;
        height: auto;
      }
    }

    .error-count {
      color: #e64340;
      font-weight: 600;
      font-size: 2.5vh;
    }

    .time-cell {
      color: #999;
      font-size: 1.83vh;
    }

    .similar-btn {
      display: inline-block;
      padding: 0.5vh 1.5vh;
      background: linear-gradient(135deg, #5fdcfd 0%, #4fc3f7 100%);
      color: #fff;
      font-size: 1.83vh;
      font-family: $font-text;
      border-radius: 0.67vh;
      white-space: nowrap;
      transition: all 0.25s;

      &:hover {
        background: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);
        box-shadow: 0 0.33vh 0.67vh rgba(95, 220, 253, 0.3);
        transform: translateY(-1px);
      }

      &:active {
        transform: translateY(0);
      }
    }

    .expand-arrow {
      display: inline-block;
      font-size: 1.67vh;
      color: #999;
      transition: transform 0.3s;

      &.expanded {
        transform: rotate(180deg);
      }
    }
  }

  .expand-section {
    border-top: 1px solid #e8f0fe;
    padding: 2vh 3vh;
    background: #f8fbff;
  }

  .expand-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5vh;
  }

  .expand-item {
    display: flex;
    align-items: flex-start;
    width: calc(50% - 0.75vh);

    &.full {
      width: 100%;
    }

    .expand-label {
      flex-shrink: 0;
      width: 10vh;
      font-size: 1.83vh;
      color: #999;
      font-family: $font-text;
      line-height: 3vh;
    }

    .expand-value {
      flex: 1;
      font-size: 1.83vh;
      color: #333;
      font-family: $font-text;
      line-height: 3vh;
      word-break: break-all;
    }

    .submit-answer {
      color: #e64340;
      font-weight: 500;
    }

    .answer-text {
      color: #2e7d32;
      font-weight: 500;
    }

    .html-content {
      :deep(img) {
        max-width: 100%;
        height: auto;
      }

      :deep(p) {
        margin: 0;
      }

      .option-item {
        display: flex;
        align-items: flex-start;
        margin-bottom: 0.5vh;

        .option-index {
          flex-shrink: 0;
          font-weight: 600;
          color: #5fadff;
          margin-right: 0.8vh;
        }

        .option-html {
          flex: 1;

          :deep(img) {
            max-width: 100%;
            height: auto;
          }
        }
      }
    }
  }
}

.retry-body {
  padding: 2vh 0;
  color: $font-color;
  line-height: 1.5;
  overflow: visible;

  &-title {
    text-align: center;
    font-family: $font-special;
    font-size: 2.33vh;
    margin-bottom: 3vh;
  }
}

.retry-form {
  padding: 0 3vh;

  &-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 2.5vh;
    row-gap: 1.5vh;
    margin-bottom: 2vh;
    position: relative;
    z-index: 10;

    & + & {
      z-index: 9;
    }
  }

  &-item {
    display: flex;
    align-items: center;
    width: 100%;
    min-width: 0; // 允许 Select 在网格中收缩，避免溢出

    label {
      flex-shrink: 0;
      width: 7vh;
      font-family: $font-text;
      font-size: 2vh;
      color: #333;
      text-align: right;
      margin-right: 1vh;
    }
  }

  &-count {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 1vh;
    padding-top: 2vh;
    border-top: 1px solid #eee;
    position: relative;
    z-index: 1;

    label {
      flex-shrink: 0;
      font-family: $font-special;
      font-size: 2.33vh;
      color: #333;
      margin-right: 2vh;
    }
  }
}

.chapter-tree-select {
  position: relative;
  width: 100%;
  z-index: 12;

  &.open {
    z-index: 1100;
  }
}

.chapter-tree-trigger {
  width: 100%;
  height: 5.33vh;
  border-radius: 1.67vh;
  background: #00000099;
  padding: 0 20px;
  box-sizing: border-box;
  color: #ffffffd9;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  font-family: $font-text;
  font-size: 2.33vh;
  line-height: 1;

  span:first-child {
    @include single_ellipsis;
  }
}

.chapter-tree-arrow {
  font-size: 2.2vh;
  color: #49e0ad;
  transition: transform 0.25s;
  line-height: 1;

  &.open {
    transform: rotate(180deg);
  }
}

.chapter-tree-panel {
  position: absolute;
  top: calc(100% + 0.83vh);
  left: 0;
  width: 100%;
  max-height: 30vh;
  border-radius: 1.67vh;
  border: 1px solid #5f676d;
  background: #4f5458;
  z-index: 1101;
  padding: 0.8vh;
  box-sizing: border-box;
  color: #ccd4d4;
}

.chapter-tree-all {
  height: 4.2vh;
  border-radius: 1vh;
  display: flex;
  align-items: center;
  padding: 0 1.2vh;
  cursor: pointer;
  font-size: 2.1vh;
  font-family: $font-text;

  &:hover,
  &.active {
    color: #fff;
    background: rgba(255, 255, 255, 0.12);
  }
}

.chapter-tree {
  margin-top: 0.6vh;
  max-height: 23vh;
  overflow: auto;
  @include hidden_scroll;
  background: transparent;

  :deep(.el-tree-node__content) {
    height: 4.2vh;
    border-radius: 0.8vh;
    color: #ccd4d4;
    font-size: 2vh;
    font-family: $font-text;
  }

  :deep(.el-tree-node__content:hover),
  :deep(.el-tree-node.is-current > .el-tree-node__content) {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
  }

  :deep(.el-tree-node__expand-icon) {
    color: #58e0ad;
  }

  :deep(.el-tree-node__label) {
    color: inherit;
  }
}

.chapter-node-label {
  color: inherit;

  &.active {
    color: #fff;
  }
}

.chapter-tree-empty {
  margin-top: 0.6vh;
  height: 12vh;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #aeb7b7;
  font-size: 1.9vh;
}

.chapter-tree-mask {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1100;
}

.retry-input {
  flex: 1;
  min-width: 0;
  height: 4.5vh;
  border: 1px solid #d9d9d9;
  border-radius: 0.67vh;
  padding: 0 1.5vh;
  font-size: 2vh;
  font-family: $font-text;
  outline: none;
  background: #fff;
  color: #333;
  transition: border-color 0.3s;
  box-sizing: border-box;

  &:focus {
    border-color: #5fdcfd;
  }

  &::placeholder {
    color: #bbb;
  }
}

.count-control {
  display: flex;
  align-items: center;
}

.count-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5vh;
  height: 5vh;
  background: linear-gradient(180deg, #e0f7fa 0%, #b2ebf2 100%);
  border-radius: 50%;
  font-size: 3vh;
  color: #00897b;
  user-select: none;
  flex-shrink: 0;
  box-shadow: 0 0.17vh 0.33vh rgba(0, 0, 0, 0.1);
  transition: background 0.2s;

  &:hover {
    background: linear-gradient(180deg, #b2ebf2 0%, #80deea 100%);
  }

  &:active {
    transform: scale(0.95);
  }
}

.count-input {
  width: 8vh;
  height: 5vh;
  text-align: center;
  border: 1px solid #d9d9d9;
  border-radius: 0.67vh;
  margin: 0 1.5vh;
  font-size: 2.67vh;
  font-family: $font-special;
  color: #333;
  outline: none;
  background: #fff;
  flex-shrink: 0;

  &:focus {
    border-color: #5fdcfd;
  }

  &::-webkit-inner-spin-button,
  &::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
}

.count-hint {
  margin-left: 1.5vh;
  font-size: 1.83vh;
  color: #999;
  font-family: $font-text;
  white-space: nowrap;
}

.record-body {
  padding: 2vh 3vh;
  display: flex;
  flex-direction: column;
  gap: 2vh;
}

.record-option {
  display: flex;
  align-items: center;
  padding: 2.5vh 3vh;
  background: linear-gradient(135deg, #f0faff 0%, #e8f4fd 100%);
  border-radius: 1.33vh;
  border: 1px solid #e0f0ff;
  transition: all 0.25s;

  &:hover {
    background: linear-gradient(135deg, #e0f4ff 0%, #d0ecfc 100%);
    box-shadow: 0 0.33vh 1vh rgba(95, 220, 253, 0.2);
    transform: translateY(-1px);
  }

  &:active {
    transform: translateY(0);
  }

  &-icon {
    font-size: 3vh;
    margin-right: 2vh;
  }

  &-text {
    flex: 1;
    font-family: $font-special;
    font-size: 2.5vh;
    color: #333;
  }

  &-arrow {
    font-size: 2vh;
    color: #999;
    transition: transform 0.2s;
  }

  &:hover &-arrow {
    transform: translateX(3px);
    color: #5fdcfd;
  }
}
</style>
