<script setup lang="ts">
import { wordTestService } from '@/api/service/word-test'
import {
  category_cn,
  category_en,
  level_type_advance,
  level_type_begin,
  result_right,
} from '@/components/word-game'
import type { Question } from '@/components/word-game'
import { globalBack } from '@/router'
import dict from '@/utils/dict'
import hud from '@/utils/hud'
import report from './report/index.vue'
import useAudio from '@/hooks/useCommonAudio'
import { OSS_URL } from '@/utils'

defineOptions({ name: 'WordTest' })

const progress = ref(0)
// 是否结束
const end = ref(false)
// 人为退出
const personalExit = ref(false)

// 是否显示答题报告
const showReport = ref(false)
const reportData = ref({} as any)

// 靠上一个界面请求后传递数据过来
const data = dict.pop('/subject/learnWord/word-test')

const questions = data?.questions as Question[]
const time = ref(data?.time as number)

// 题目的答题情况(spell是key，value是答题情况{select: true, spell: true})
// select是选择题，spell是拼写题
const questionResult = {} as any

// 当前的题目索引
const curQuestionIndex = ref(0)

// 正确的题目数量
const rightCount = ref(0)

// 当前的题目
const curQuestion = computed(() => {
  return questions?.[curQuestionIndex.value] || {}
})

// 倒计时
const leftTime = computed(() => {
  if (!time.value) return 0
  const h = parseInt(String((time.value / 60 / 60) % 24), 10)
  const m = parseInt(String((time.value / 60) % 60), 10)
  const s = parseInt(String(time.value % 60), 10)

  if (time.value === undefined) return

  if (h > 0) {
    return `${h}h ${m}m`
  } else if (m > 0) {
    return `${m}m ${s}s`
  } else if (s > 0) {
    return `${s}s`
  } else {
    return '0'
  }
})

// 最好连击
const comboNum = ref(0)

// 底部的标题
const bottomTitle = computed(() => {
  const stageName = data.extra?.stageName
  if (stageName) return stageName
  const book = data.extra?.book
  if (!book) return ''
  return `${book.versionName}-${book.bookName}`
})

// 退出的确认
function confirmExit() {
  if (end.value) {
    globalBack()
  } else {
    hud.alert({
      content: '确认退出？',
      ok: async () => {
        const cost = data?.time - time.value
        if (cost > 10) {
          // 超过10秒才统计
          personalExit.value = true
          end.value = true
        } else {
          globalBack()
        }
      },
    })
  }
}

// 开始倒计时定时器
let failedTimer = undefined as any
function startFailedTimer() {
  stopFailedTimer()

  failedTimer = setInterval(() => {
    time.value--

    if (time.value === 0) {
      hud.error('很遗憾，时间到了！')
      end.value = true
    }
  }, 1000)
}

// 结束定时器
function stopFailedTimer() {
  clearInterval(failedTimer)
}

const showCombo = ref(false)
watch(
  () => showCombo.value,
  nv => {
    if (nv) {
      setTimeout(() => {
        showCombo.value = false
      }, 1000)
    }
  },
)

// 是否为最后一题
const last = computed(() => curQuestionIndex.value === questions?.length - 1)

// 进入下一题
function toNextQuestion() {
  if (last.value) return
  curQuestionIndex.value++
}

// 处理结果
async function handlePostResult(result: any, surrender: any, duration: any) {
  // 进度条
  progress.value = Math.trunc(((curQuestionIndex.value + 1) / questions.length) * 100)

  if (result === result_right) {
    // 回答正确
    rightCount.value++
    // 增加连击数
    comboNum.value++
    if (comboNum.value > 1) {
      showCombo.value = true
    }
  } else {
    // 回答错误
    comboNum.value = 0
  }

  // 拿到当前题目
  const q = curQuestion.value

  // 是否答对
  const isRight = result === result_right

  // 记录答题情况
  const info = questionResult[q.wordSpell]

  // 获取题目类型
  let questionType = -1
  if (q.levelType === level_type_advance) {
    questionType = 3
    info.spell = isRight
  } else if (q.titleCategory === category_en) {
    questionType = 0
    info.select = isRight
  } else if (q.titleCategory === category_cn) {
    questionType = 1
    info.select = isRight
  }

  const willEnd = progress.value === 100
  if (willEnd) {
    hud.loading('正在保存中')
  }

  try {
    // 保存单题目的结果
    await wordTestService.saveWordRecord({
      sessionId: q.sessionId,
      wordId: q.wordId,
      meaningId: q.meaningId,
      testResult: isRight ? 1 : 0,
      surrender: surrender ? 1 : 0,
      questionType,
      duration,
    })
  } finally {
    if (willEnd) {
      // 如果是最后一题
      end.value = true
    }
  }
}

function submitError() {
  hud.alert({
    title: '保存失败',
    content: '是否重新保存？',
    hideClose: true,
    maskClose: false,
    cancelText: '退出',
    ok: async () => {
      submit()
    },
    cancel: () => {
      globalBack()
    },
  })
}

// 播放
const sound = useAudio()

async function submit() {
  if (!hud.isLoading()) {
    hud.loading('正在保存中')
  }

  try {
    const wordGraspInfo = {
      strangeCount: 0, // 陌生
      knowCount: 0, // 认识
      knowWellCount: 0, // 熟悉
      graspCount: 0, // 掌握
    }
    // 统计掌握程度
    for (const spell in questionResult) {
      const res = questionResult[spell]
      if (res.select && res.spell) {
        wordGraspInfo.graspCount++
      } else if (res.select) {
        wordGraspInfo.knowCount++
      } else if (res.spell) {
        wordGraspInfo.knowWellCount++
      } else {
        wordGraspInfo.strangeCount++
      }
    }
    // 发送请求
    reportData.value = await wordTestService.saveTotalRecords({
      sessionId: curQuestion.value.sessionId,
      rightNum: rightCount.value, // 正确数
      comboNum: comboNum.value, // 连击数
      exitReason: personalExit.value ? 2 : time.value <= 0 ? 1 : 0,
      wordGraspInfo,
    })
    showReport.value = true

    // 播放音频
    const rightRate = Math.trunc((rightCount.value / questions.length) * 10000)
    if (rightRate >= 10000) {
      sound.play(`${OSS_URL}/sound/report_100.mp3`)
    } else if (rightRate > 0) {
      sound.play(`${OSS_URL}/sound/report_99.mp3`)
    } else {
      sound.play(`${OSS_URL}/sound/report_0.mp3`)
    }
  } catch (error) {
    console.error(error)
    submitError()
  } finally {
    hud.hideLoading()
  }
}

watch(
  () => end.value,
  () => {
    if (!end.value) return

    // 停止定时器
    stopFailedTimer()

    // 提交最终请求
    submit()
  },
)

onMounted(() => {
  if (!data) {
    globalBack()
    return
  }

  // 先初始化答题情况
  for (const q of questions) {
    questionResult[q.wordSpell] = {
      spell: false,
      select: false,
    }
  }

  startFailedTimer()
})

onUnmounted(() => {
  stopFailedTimer()
})
</script>

<template>
  <div v-if="data" class="word-test">
    <BackBar class="back-bar" show-only @click="confirmExit" />
    <new-progress-bar class="progress-bar" :progress="progress" />
    <div class="title-bar">
      <heart-bg />
      <div class="title-item">倒计时：{{ leftTime }}</div>
      <div class="title-item">
        正确：<span :class="{ 'right-count': rightCount }">{{ rightCount }}</span
        >/{{ questions?.length }}
      </div>
      <div class="title-item">最好连击：{{ comboNum }}</div>
    </div>
    <div class="content">
      <word-single-choice
        v-if="curQuestion.levelType === level_type_begin"
        :data="curQuestion as any"
        :last="last"
        :end="end"
        count-down
        @post-result="handlePostResult"
        @next="toNextQuestion"
      />
      <word-spelling-bee
        v-if="curQuestion.levelType === level_type_advance"
        :end="end"
        open
        :data="curQuestion as any"
        :last="last"
        count-down
        @post-result="handlePostResult"
        @next="toNextQuestion"
      />
      <WinningStreakAnimation v-if="showCombo" :num="comboNum" />
    </div>
    <div class="bottom-title">{{ bottomTitle }}</div>
    <div id="learn-audio"></div>
  </div>
  <report v-model="showReport" :data="reportData" @ok="globalBack" />
</template>

<style lang="scss" scoped>
.word-test {
  position: relative;
  height: 100%;
  overflow: auto;
  padding-top: 2.67vh;
  @include main_bg;

  .right-count {
    color: #42c20b;
  }

  .title-bar {
    position: relative;
    width: 1085px;
    height: 7.67vh;
    background-color: #a0fcf8;
    border-top-left-radius: 40px;
    border-top-right-radius: 40px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    overflow: hidden;

    .title-item {
      flex: 1;
      text-align: center;
      font-size: 3.33vh;
      font-family: $font-text;
      color: rgba(0, 0, 0, 0.65);
      z-index: 1;
    }
  }

  .content {
    padding: 0 32px;
    position: relative;
    top: -0.08vh;
  }

  .back-bar {
    position: absolute;
    top: 2.67vh;
    left: $space-6;
    z-index: 1;
  }

  .progress-bar {
    position: absolute;
    top: 2.67vh;
    right: 32px;
    z-index: 1;
  }

  .bottom-title {
    text-align: center;
    color: #4b4b68;
    font-size: 2.33vh;
    height: 2.67vh;
    line-height: 2.67vh;
    margin-top: 1vh;
    font-family: $font-text;
  }
}
</style>
