<script setup lang="ts">
import { computed, nextTick, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import {
  api,
  type CoachTurnResponse,
  type CoachWordBrief,
  type MemoryToken,
  type QuizTrack,
} from '../api/request'
import { useQuizTimer } from '../composables/useQuizTimer'

interface ChatLine {
  role: 'assistant' | 'user'
  content: string
}

const route = useRoute()
const track = computed<QuizTrack>(() =>
  route.query.track === 'book' ? 'book' : 'accumulation'
)
const pageTitle = computed(() =>
  track.value === 'book' ? '词书记忆对话' : '积累记忆对话'
)

const { startQuestionTimer, consumeDurationSeconds } = useQuizTimer()

const loading = ref(true)
const empty = ref(false)
const words = ref<CoachWordBrief[]>([])
const wordIndex = ref(0)
const stage = ref('intro')
const hintsUsed = ref(0)
const tokens = ref<MemoryToken[]>([])
const promptZh = ref('')
const promptPhonetic = ref<string | null>(null)
const chatLines = ref<ChatLine[]>([])
const userInput = ref('')
const sending = ref(false)
const expectInput = ref(false)
const sessionDone = ref(false)
const showTokens = ref(false)
const chatEndRef = ref<HTMLElement | null>(null)

const currentWord = computed(() => words.value[wordIndex.value])

const promptLabel = computed(() => promptZh.value || currentWord.value?.zh || '')

const phoneticLabel = computed(
  () => promptPhonetic.value || currentWord.value?.phonetic || ''
)

const inputPlaceholder = computed(() => {
  const zh = promptLabel.value
  return zh ? `输入「${zh}」的英文` : '输入英文'
})

const kTokens = computed(() => tokens.value.filter((t) => t.role === 'K'))
const qTokens = computed(() => tokens.value.filter((t) => t.role === 'Q'))
const vTokens = computed(() => tokens.value.filter((t) => t.role === 'V' && t.revealed))

function tokenClass(role: string) {
  if (role === 'Q') return 'pill-q'
  if (role === 'K') return 'pill-k'
  return 'pill-v'
}

function scrollChat() {
  nextTick(() => {
    chatEndRef.value?.scrollIntoView({ behavior: 'smooth' })
  })
}

function appendAssistant(msgs: string[]) {
  for (const m of msgs) {
    if (m.trim()) chatLines.value.push({ role: 'assistant', content: m })
  }
  scrollChat()
}

function applyTurn(res: CoachTurnResponse) {
  tokens.value = res.tokens ?? []
  stage.value = res.stage
  expectInput.value = res.expect_input
  hintsUsed.value = res.hints_used
  if (res.prompt_zh) promptZh.value = res.prompt_zh
  if (res.prompt_phonetic !== undefined) promptPhonetic.value = res.prompt_phonetic
  appendAssistant(res.assistant_messages)
}

async function runTurn(message: string) {
  const w = currentWord.value
  if (!w || sending.value) return
  sending.value = true
  try {
    const duration =
      stage.value === 'derive' && message
        ? consumeDurationSeconds()
        : undefined
    const { data } = await api.coachTurn({
      word_id: w.word_id,
      stage: stage.value,
      user_message: message,
      hints_used: hintsUsed.value,
      duration_seconds: duration,
    })
    applyTurn(data)
    if (data.word_complete && data.stage === 'done') {
      expectInput.value = false
    }
  } finally {
    sending.value = false
  }
}

async function startCurrentWord() {
  const w = currentWord.value
  chatLines.value = []
  stage.value = 'intro'
  hintsUsed.value = 0
  userInput.value = ''
  showTokens.value = false
  promptZh.value = w?.zh ?? ''
  promptPhonetic.value = w?.phonetic ?? null
  startQuestionTimer()
  await runTurn('')
}

async function sendMessage() {
  const text = userInput.value.trim()
  if (!text) return
  chatLines.value.push({ role: 'user', content: text })
  userInput.value = ''
  scrollChat()
  await runTurn(text)
}

function nextWord() {
  if (wordIndex.value >= words.value.length - 1) {
    sessionDone.value = true
    return
  }
  wordIndex.value += 1
  startCurrentWord()
}

onMounted(async () => {
  try {
    const { data } = await api.coachSession(track.value)
    words.value = data.words
    empty.value = data.total === 0
    if (!empty.value) await startCurrentWord()
  } finally {
    loading.value = false
  }
})
</script>

<template>
  <div class="page coach-page">
    <header class="coach-header">
      <h1 class="page-title">{{ pageTitle }}</h1>
      <span v-if="!empty && !sessionDone" class="coach-count">
        {{ wordIndex + 1 }} / {{ words.length }}
      </span>
    </header>

    <p v-if="loading" class="muted">加载中...</p>
    <p v-else-if="empty" class="muted">
      暂无待练单词，<router-link to="/translate">去加词</router-link>
    </p>

    <template v-else-if="!sessionDone">
      <section class="coach-main card">
        <p v-if="promptLabel" class="coach-zh">{{ promptLabel }}</p>
        <p v-if="phoneticLabel" class="coach-phonetic">{{ phoneticLabel }}</p>
        <p v-if="currentWord" class="coach-meta">
          记忆 {{ currentWord.retention_now }}% · 掌握 {{ currentWord.mastery_score }}%
          <span class="qkv-hint">· K/Q/V 推导</span>
        </p>

        <button type="button" class="token-toggle" @click="showTokens = !showTokens">
          {{ showTokens ? '收起线索' : '展开 Q/K/V 线索' }}
          <span v-if="hintsUsed" class="hint-badge">{{ hintsUsed }}</span>
        </button>

        <div v-if="showTokens && tokens.length" class="token-groups">
          <div v-if="kTokens.length" class="token-group">
            <span class="group-tag pill-k">K</span>
            <span
              v-for="t in kTokens"
              :key="t.key"
              class="pill"
              :class="tokenClass('K')"
            >
              {{ t.label }} {{ t.value }}
            </span>
          </div>
          <div v-if="qTokens.length" class="token-group">
            <span class="group-tag pill-q">Q</span>
            <span
              v-for="t in qTokens"
              :key="t.key"
              class="pill"
              :class="[tokenClass('Q'), { dim: !t.revealed }]"
            >
              {{ t.label }} {{ t.revealed ? t.value : '…' }}
            </span>
          </div>
          <div v-if="vTokens.length" class="token-group">
            <span class="group-tag pill-v">V</span>
            <span
              v-for="t in vTokens"
              :key="t.key"
              class="pill"
              :class="tokenClass('V')"
            >
              {{ t.label }} {{ t.value }}
            </span>
          </div>
        </div>

        <div v-if="chatLines.length" class="chat-feed">
          <div
            v-for="(line, i) in chatLines"
            :key="i"
            class="chat-line"
            :class="line.role"
          >
            {{ line.content }}
          </div>
          <div ref="chatEndRef" />
        </div>

        <div v-if="expectInput" class="input-bar">
          <input
            v-model="userInput"
            class="input"
            type="text"
            :placeholder="inputPlaceholder"
            autocomplete="off"
            autocapitalize="off"
            @keydown.enter.prevent="sendMessage"
          />
          <button
            type="button"
            class="btn btn-primary send-btn"
            :disabled="sending"
            @click="sendMessage"
          >
            提交
          </button>
        </div>

        <button
          v-else-if="stage === 'done'"
          type="button"
          class="btn btn-primary next-btn"
          @click="nextWord"
        >
          {{ wordIndex >= words.length - 1 ? '完成' : '下一个' }}
        </button>
      </section>
    </template>

    <section v-else class="card done-card">
      <p>本轮已完成</p>
      <router-link to="/" class="btn btn-outline">回首页</router-link>
    </section>
  </div>
</template>

<style scoped>
.coach-page {
  padding-bottom: 24px;
}
.coach-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.coach-header .page-title {
  margin: 0;
}
.coach-count {
  font-size: 14px;
  color: var(--muted);
  font-weight: 600;
}
.muted {
  color: var(--muted);
  font-size: 14px;
}
.coach-main {
  padding: 20px 16px;
}
.coach-zh {
  font-size: 28px;
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 4px;
}
.coach-phonetic {
  font-size: 15px;
  color: var(--muted);
  margin: 0 0 8px;
}
.coach-meta {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 12px;
}
.qkv-hint {
  opacity: 0.85;
}
.token-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  border: none;
  background: none;
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 10px;
}
.hint-badge {
  background: var(--primary);
  color: #fff;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 10px;
}
.token-groups {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: 10px;
}
.token-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.group-tag {
  font-size: 11px;
  font-weight: 800;
  padding: 2px 6px;
  border-radius: 4px;
}
.pill {
  font-size: 12px;
  padding: 4px 8px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: #fff;
}
.pill.dim {
  opacity: 0.5;
  border-style: dashed;
}
.pill-k,
.group-tag.pill-k {
  background: #f5f3ff;
  color: #5b21b6;
  border-color: #ddd6fe;
}
.pill-q,
.group-tag.pill-q {
  background: #eff6ff;
  color: #1d4ed8;
  border-color: #bfdbfe;
}
.pill-v,
.group-tag.pill-v {
  background: #ecfdf5;
  color: #047857;
  border-color: #a7f3d0;
}
.chat-feed {
  max-height: 28vh;
  overflow-y: auto;
  margin-bottom: 14px;
  padding-top: 4px;
}
.chat-line {
  font-size: 14px;
  line-height: 1.5;
  margin-bottom: 8px;
}
.chat-line.user {
  color: var(--primary);
  font-weight: 600;
  text-align: right;
}
.chat-line.assistant {
  color: var(--text);
}
.input-bar {
  display: flex;
  gap: 8px;
}
.input-bar .input {
  flex: 1;
  margin: 0;
}
.send-btn {
  width: auto;
  min-width: 64px;
  padding: 12px 14px;
}
.next-btn {
  margin-top: 4px;
}
.done-card {
  text-align: center;
  padding: 28px 20px;
}
.done-card p {
  margin-bottom: 16px;
}
</style>
