<script setup lang="ts">
import { computed } from 'vue'
import type { ChapterInfo, SceneNode } from '@engine/types'

const props = defineProps<{
  chapter: ChapterInfo
  scenes: Record<string, SceneNode>
  visitedIds: Set<string>
}>()

const emit = defineEmits<{
  close: []
}>()

function collectReachable(startId: string): Set<string> {
  const visited = new Set<string>()
  const queue = [startId]
  while (queue.length > 0) {
    const id = queue.shift()!
    if (visited.has(id)) continue
    const scene = props.scenes[id]
    if (!scene) continue
    visited.add(id)
    if (scene.choices) {
      for (const c of scene.choices) {
        if (c.targetScene && !visited.has(c.targetScene)) queue.push(c.targetScene)
      }
    }
    if (scene.nextScene && !visited.has(scene.nextScene)) queue.push(scene.nextScene)
    if (scene.qte) {
      if (scene.qte.successScene && !visited.has(scene.qte.successScene)) queue.push(scene.qte.successScene)
      if (scene.qte.failScene && !visited.has(scene.qte.failScene)) queue.push(scene.qte.failScene)
    }
    if (scene.hotspots) {
      for (const h of scene.hotspots) {
        if (h.targetScene && !visited.has(h.targetScene)) queue.push(h.targetScene)
      }
    }
  }
  return visited
}

const reachable = computed(() => collectReachable(props.chapter.startScene))

const visitedCount = computed(() => {
  let count = 0
  for (const id of reachable.value) {
    if (props.visitedIds.has(id)) count++
  }
  return count
})

const totalCount = computed(() => reachable.value.size)

const percentage = computed(() => {
  if (totalCount.value === 0) return 0
  return Math.round((visitedCount.value / totalCount.value) * 100)
})

const sceneList = computed(() => {
  return [...reachable.value].map((id) => {
    const scene = props.scenes[id]
    const isVisited = props.visitedIds.has(id)
    let hint = ''

    if (!isVisited) {
      // Find why this scene is locked - look at conditions from scenes that lead to it
      for (const [srcId, src] of Object.entries(props.scenes)) {
        if (src.choices) {
          for (const c of src.choices) {
            if (c.targetScene === id && c.conditions && c.conditions.length > 0) {
              const firstCond = c.conditions[0]
              hint = `${firstCond.variable} ${firstCond.op} ${firstCond.value}`
              break
            }
          }
        }
        if (src.hotspots) {
          for (const h of src.hotspots) {
            if (h.targetScene === id && h.conditions && h.conditions.length > 0) {
              const firstCond = h.conditions[0]
              hint = `${firstCond.variable} ${firstCond.op} ${firstCond.value}`
              break
            }
          }
        }
        if (hint) break
      }
    }

    return { id, label: scene?.id ?? id, isVisited, hint }
  })
})
</script>

<template>
  <div class="recap-overlay" @click.self="emit('close')" @keydown.escape="emit('close')">
    <div class="recap-panel">
      <h2 class="recap-title">{{ chapter.label }} - 回顾</h2>

      <div class="recap-progress">
        <div class="progress-bar">
          <div class="progress-fill" :style="{ width: percentage + '%' }"></div>
        </div>
        <div class="progress-text">{{ visitedCount }} / {{ totalCount }} 场景已发现 ({{ percentage }}%)</div>
      </div>

      <div class="recap-list">
        <div
          v-for="item in sceneList"
          :key="item.id"
          class="recap-item"
          :class="{ visited: item.isVisited }"
        >
          <span class="recap-icon">{{ item.isVisited ? '✅' : '⬜' }}</span>
          <span class="recap-label">{{ item.label }}</span>
          <span v-if="!item.isVisited && item.hint" class="recap-hint">🔒 {{ item.hint }}</span>
        </div>
      </div>

      <button class="recap-close" @click="emit('close')">关闭</button>
    </div>
  </div>
</template>

<style scoped>
.recap-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.recap-panel {
  background: #1a1a2e;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  padding: 36px 40px;
  min-width: 420px;
  max-width: 520px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.recap-title {
  text-align: center;
  font-size: 20px;
  font-weight: 400;
  color: #ddd;
  letter-spacing: 2px;
  margin-bottom: 20px;
}

.recap-progress {
  margin-bottom: 20px;
}

.progress-bar {
  height: 6px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 3px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: #4caf50;
  border-radius: 3px;
  transition: width 0.4s ease;
}

.progress-text {
  margin-top: 8px;
  font-size: 13px;
  color: #aaa;
  text-align: center;
}

.recap-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  padding-right: 8px;
}

.recap-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.03);
  border-radius: 4px;
  font-size: 13px;
}

.recap-item.visited {
  background: rgba(76, 175, 80, 0.08);
}

.recap-icon {
  font-size: 14px;
  flex-shrink: 0;
}

.recap-label {
  color: #ccc;
  flex: 1;
}

.recap-item.visited .recap-label {
  color: #fff;
}

.recap-hint {
  font-size: 11px;
  color: #ff9800;
  white-space: nowrap;
}

.recap-close {
  margin-top: 20px;
  padding: 10px 36px;
  font-size: 14px;
  color: #888;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  align-self: center;
}

.recap-close:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #ccc;
}
</style>
