<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import * as booksApi from '../services/booksApi'
import {
  assembleContent,
  matchToc,
  parseZip,
  type BookEntry,
  type ProposedLesson,
} from '../services/bookImport'
import type { BookLessonInput } from '../composables/useTeachingBook'
import UploadDropzone from './UploadDropzone.vue'

type Phase = 'input' | 'division-loading' | 'preview' | 'running' | 'done' | 'error'

const props = defineProps<{
  running: boolean
  done: number
  total: number
  currentTopic: string
  error: string | null
}>()

const emit = defineEmits<{
  start: [lessons: BookLessonInput[]]
  cancel: []
  close: []
}>()

const phase = ref<Phase>('input')
const tocText = ref('')
const zipFile = ref<File | null>(null)
const inputError = ref<string | null>(null)

const entries = ref<BookEntry[]>([])
const lessons = ref<ProposedLesson[]>([])

const matchedCount = computed(() => entries.value.filter((e) => e.matched).length)

watch(
  () => props.running,
  (val) => {
    if (!val && phase.value === 'running') {
      phase.value = props.error ? 'error' : 'done'
    }
  },
)

function onFiles(files: File[]): void {
  const file = files[0]
  if (!file) return
  if (!/\.zip$/i.test(file.name)) {
    inputError.value = '请上传 .zip 压缩包。'
    return
  }
  inputError.value = null
  zipFile.value = file
}

function chapterTitlesOf(lesson: ProposedLesson): string {
  return lesson.sourceIndexes
    .map((i) => entries.value.find((e) => e.index === i)?.title ?? '')
    .filter(Boolean)
    .join('、')
}

async function handleAnalyze(): Promise<void> {
  if (!tocText.value.trim() || !zipFile.value) return
  inputError.value = null
  phase.value = 'division-loading'

  try {
    const map = await parseZip(zipFile.value)
    entries.value = matchToc(tocText.value, map)
  } catch {
    inputError.value = '压缩包解析失败，请确认是有效的 .zip 文件。'
    phase.value = 'input'
    return
  }

  if (entries.value.length === 0) {
    inputError.value = '目录为空。'
    phase.value = 'input'
    return
  }

  try {
    const result = await booksApi.divideLessonsFromBook(
      entries.value.map((e) => ({ index: e.index, title: e.title, charCount: e.charCount })),
    )
    lessons.value = result.lessons
    phase.value = 'preview'
  } catch (error) {
    inputError.value = error instanceof Error ? error.message : 'AI 划分课时失败。'
    phase.value = 'input'
  }
}

function removeLesson(index: number): void {
  lessons.value.splice(index, 1)
}

function handleStart(): void {
  const payload: BookLessonInput[] = lessons.value
    .filter((lesson) => lesson.title.trim() !== '')
    .map((lesson) => ({
      title: lesson.title.trim(),
      content: assembleContent(lesson, entries.value),
    }))
  if (payload.length === 0) return
  phase.value = 'running'
  emit('start', payload)
}

function handleClose(): void {
  phase.value = 'input'
  tocText.value = ''
  zipFile.value = null
  inputError.value = null
  entries.value = []
  lessons.value = []
  emit('close')
}
</script>

<template>
  <div class="dialog-overlay" role="dialog" aria-modal="true" aria-labelledby="book-import-title">
    <div class="dialog batch-dialog">
      <h2 id="book-import-title">从书籍生成教案</h2>

      <!-- 第一步：粘贴目录 + 上传 ZIP -->
      <template v-if="phase === 'input'">
        <p>粘贴教材目录（每行一个标题），并上传内含各章 .md 的 ZIP（文件名为目录标题）。AI 将据此划分课时。</p>
        <p v-if="inputError" class="app-notice app-notice--error" role="alert">{{ inputError }}</p>
        <textarea
          v-model="tocText"
          class="batch-topics-input"
          rows="12"
          placeholder="第1章 C# 入门&#10;第2章 变量与数据类型&#10;第3章 流程控制"
        />
        <UploadDropzone accept=".zip,application/zip" :multiple="false" @files="onFiles" />
        <p v-if="zipFile" class="book-import-file">已选：{{ zipFile.name }}</p>
        <div class="dialog-actions">
          <button type="button" :disabled="!tocText.trim() || !zipFile" @click="handleAnalyze">
            解析并划分课时
          </button>
          <button type="button" @click="handleClose">取消</button>
        </div>
      </template>

      <!-- AI 划分中 -->
      <template v-else-if="phase === 'division-loading'">
        <p>AI 正在划分课时…</p>
      </template>

      <!-- 第二步：预览/编辑课时 -->
      <template v-else-if="phase === 'preview'">
        <p>
          目录共 {{ entries.length }} 行，匹配到正文 {{ matchedCount }} 行。AI 划分出以下课时，可编辑标题或删除后开始生成：
        </p>
        <ul class="book-import-lessons">
          <li v-for="(lesson, index) in lessons" :key="index" class="book-import-lesson">
            <input v-model="lesson.title" type="text" class="book-import-lesson-title" />
            <span class="book-import-lesson-source">{{ chapterTitlesOf(lesson) || '（无匹配正文）' }}</span>
            <button type="button" class="book-import-lesson-remove" @click="removeLesson(index)">删除</button>
          </li>
        </ul>
        <p class="batch-topics-count">共 {{ lessons.length }} 个课时</p>
        <div class="dialog-actions">
          <button type="button" :disabled="lessons.length === 0" @click="handleStart">开始生成</button>
          <button type="button" @click="phase = 'input'">重新选择</button>
        </div>
      </template>

      <!-- 生成中 -->
      <template v-else-if="phase === 'running'">
        <p class="batch-progress-label">
          正在生成第 <strong>{{ done + 1 }}</strong> / {{ total }} 篇
        </p>
        <p class="batch-current-topic">{{ currentTopic }}</p>
        <div class="batch-progress-bar">
          <div class="batch-progress-fill" :style="{ width: `${(done / total) * 100}%` }" />
        </div>
        <div class="dialog-actions">
          <button type="button" @click="emit('cancel')">停止</button>
        </div>
      </template>

      <!-- 出错 -->
      <template v-else-if="phase === 'error'">
        <p class="app-notice app-notice--error" role="alert">{{ error }}</p>
        <p>已生成 {{ done }} / {{ total }} 篇，生成中止。</p>
        <div class="dialog-actions">
          <button type="button" @click="handleClose">关闭</button>
        </div>
      </template>

      <!-- 完成 -->
      <template v-else-if="phase === 'done'">
        <p>已生成 <strong>{{ done }}</strong> / {{ total }} 篇教案。</p>
        <div class="dialog-actions">
          <button type="button" @click="handleClose">关闭</button>
        </div>
      </template>
    </div>
  </div>
</template>
