<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import NewGameModal from './components/NewGameModal.vue'
import WordModal from './components/WordModal.vue'
import { PRESET_TOPICS, wordlistUrl } from './logic/topics'
import { parseWordlist, pickWords, wordKeyOf, type Word } from './logic/wordlist'
import { addSeen, loadState, saveState, type GameState } from './logic/storage'

const game = ref<GameState | null>(null)
const seenWords = ref<string[]>([])
const showConfig = ref(false)
const showWord = ref(false)
const loading = ref(false)
const errorMsg = ref<string | null>(null)

onMounted(() => {
  const s = loadState()
  game.value = s.game
  seenWords.value = s.seenWords
})

watch(
  [game, seenWords],
  () => saveState({ game: game.value, seenWords: seenWords.value }),
  { deep: true },
)

const currentWord = computed<Word | null>(() => {
  if (!game.value) return null
  if (game.value.currentIndex >= game.value.queue.length) return null
  return game.value.queue[game.value.currentIndex]
})

const isComplete = computed(() => {
  if (!game.value) return false
  return game.value.currentIndex >= game.value.queue.length
})

const remaining = computed(() => {
  if (!game.value) return 0
  return Math.max(0, game.value.queue.length - game.value.currentIndex)
})

function difficultyLabel(d: 1 | 2 | 3): string {
  return d === 1 ? '简单' : d === 2 ? '中等' : '困难'
}

async function fetchTopic(topic: string): Promise<Word[]> {
  const res = await fetch(wordlistUrl(topic))
  if (!res.ok) throw new Error(`无法加载主题 ${topic}（${res.status}）`)
  return parseWordlist(await res.text())
}

async function loadPool(topic: string | null): Promise<Word[]> {
  if (topic) {
    return await fetchTopic(topic)
  }
  const all = await Promise.all(PRESET_TOPICS.map((t) => fetchTopic(t.value).catch(() => [] as Word[])))
  return all.flat()
}

async function onStart(cfg: { topic: string | null; difficulty: 1 | 2 | 3; totalWords: number }) {
  loading.value = true
  errorMsg.value = null
  try {
    const pool = await loadPool(cfg.topic)
    if (pool.length === 0) {
      errorMsg.value = `主题 "${cfg.topic ?? 'any'}" 没有可用单词`
      return
    }
    const seenSet = new Set(seenWords.value)
    const picked = pickWords(pool, cfg.difficulty, cfg.totalWords, seenSet)
    if (picked.length === 0) {
      errorMsg.value = '无法生成单词，请换一个主题或难度'
      return
    }
    game.value = {
      config: { topic: cfg.topic, difficulty: cfg.difficulty, totalWords: cfg.totalWords },
      queue: picked,
      currentIndex: 0,
      correctCount: 0,
      passCount: 0,
    }
    seenWords.value = addSeen(seenWords.value, picked.map(wordKeyOf))
    showConfig.value = false
  } catch (e) {
    errorMsg.value = (e as Error).message
  } finally {
    loading.value = false
  }
}

function onCorrect() {
  if (!game.value || isComplete.value) return
  game.value = {
    ...game.value,
    correctCount: game.value.correctCount + 1,
    currentIndex: game.value.currentIndex + 1,
  }
  if (isComplete.value) showWord.value = false
}
function onPass() {
  if (!game.value || isComplete.value) return
  game.value = {
    ...game.value,
    passCount: game.value.passCount + 1,
    currentIndex: game.value.currentIndex + 1,
  }
  if (isComplete.value) showWord.value = false
}
function reset() {
  if (!confirm('确定重置游戏？')) return
  game.value = null
}
</script>

<template>
  <main>
    <header class="topbar">
      <h1>🎴 Articulate</h1>
      <div class="actions">
        <button v-if="game" class="ghost" @click="reset">重置</button>
        <button class="primary" @click="showConfig = true">{{ game ? '新一轮' : '开始游戏' }}</button>
      </div>
    </header>

    <p v-if="errorMsg" class="error">{{ errorMsg }}</p>

    <section v-if="loading" class="hint-block">
      <p>加载词库中...</p>
    </section>

    <section v-else-if="!game" class="hint-block">
      <p>中英猜词游戏：选好主题、难度、词数 → 一人描述，全队猜。</p>
      <p class="dim">看到中文不能说英文 / 看到英文不能说中文。猜对按 ✓，跳过按 →。</p>
    </section>

    <section v-else class="board">
      <div v-if="!isComplete && currentWord" class="word" @click="showWord = true">
        <div class="zh">{{ currentWord.chinese }}</div>
        <div class="en">{{ currentWord.english }}</div>
      </div>
      <div v-else class="done">
        <div class="emoji">🎉</div>
        <h2>游戏结束</h2>
        <p>所有单词已完成</p>
      </div>

      <div class="actions-row">
        <button class="ok" :disabled="isComplete" @click="onCorrect">
          <span class="ic">✓</span> 猜对了
        </button>
        <button class="warn" :disabled="isComplete" @click="onPass">
          <span class="ic">→</span> 跳过
        </button>
      </div>

      <div class="stats">
        <div class="stat ok"><div class="lbl">猜对</div><div class="val">{{ game.correctCount }}</div></div>
        <div class="stat warn"><div class="lbl">跳过</div><div class="val">{{ game.passCount }}</div></div>
        <div class="stat info"><div class="lbl">剩余</div><div class="val">{{ remaining }}</div></div>
      </div>

      <div class="info">
        <span v-if="game.config.topic">主题：{{ game.config.topic }}</span>
        <span>难度：{{ difficultyLabel(game.config.difficulty) }}</span>
        <span>已记忆 {{ seenWords.length }} 词</span>
      </div>
    </section>

    <WordModal
      :show="showWord"
      :word="currentWord"
      :is-complete="isComplete"
      @close="showWord = false"
      @correct="onCorrect"
      @pass="onPass"
    />
    <NewGameModal
      :show="showConfig"
      :initial="game?.config"
      @close="showConfig = false"
      @start="onStart"
    />
  </main>
</template>

<style scoped>
main {
  max-width: 600px;
  margin: 0 auto;
  padding: 16px 16px 40px;
}
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
h1 { margin: 0; font-size: 1.5rem; }
.actions { display: flex; gap: 8px; }
button.primary { background: var(--accent); border: none; color: white; padding: 10px 16px; border-radius: 8px; font-weight: bold; }
button.ghost { background: transparent; border: 1px solid var(--border); color: var(--fg); padding: 10px 14px; border-radius: 8px; }

.error { background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.4); color: #ff8080; padding: 10px 14px; border-radius: 8px; }
.hint-block { padding: 30px; text-align: center; background: var(--bg-soft); border-radius: 12px; color: var(--fg-dim); }
.hint-block .dim { font-size: 0.85rem; opacity: 0.7; margin-top: 12px; }

.word {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 16px;
  padding: 28px 20px;
  text-align: center;
  cursor: pointer;
  margin-bottom: 20px;
  box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
}
.zh { font-size: 3rem; font-weight: bold; line-height: 1.1; margin-bottom: 8px; }
.en { font-size: 2rem; opacity: 0.9; line-height: 1.1; }

.done {
  text-align: center;
  background: var(--bg-soft);
  border-radius: 16px;
  padding: 40px;
  margin-bottom: 20px;
}
.done .emoji { font-size: 60px; margin-bottom: 8px; }
.done h2 { margin: 4px 0; }

.actions-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px;
}
.actions-row button {
  padding: 18px;
  border: none;
  border-radius: 12px;
  color: white;
  font-size: 1.1rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.actions-row button.ok { background: linear-gradient(135deg, #4CAF50, #45a049); }
.actions-row button.warn { background: linear-gradient(135deg, #FF9800, #F57C00); }
.actions-row button:disabled { background: #444; color: #888; }
.ic { font-size: 1.1rem; }

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 16px; }
.stat {
  background: var(--bg-soft);
  border-radius: 8px;
  padding: 10px 12px;
  border-left: 4px solid var(--border);
}
.stat.ok { border-left-color: var(--accent); }
.stat.warn { border-left-color: var(--warn); }
.stat.info { border-left-color: #2196F3; }
.lbl { font-size: 0.78rem; color: var(--fg-dim); }
.val { font-size: 1.2rem; font-weight: bold; }

.info {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 0.85rem;
  color: var(--fg-dim);
  padding: 12px;
  background: var(--bg-soft);
  border-radius: 8px;
  justify-content: center;
}
</style>
