<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import { useRoute, useRouter } from "vue-router";
import {
  getStandardMindMap,
  regenerateStandardMindMap,
  recallCompare,
  updateStandardMindMap,
  listRecallRecords,
  type StandardMindMap,
  type RecallRecord,
} from "@/api/standardMindMap";
import { ElMessage, ElMessageBox } from "element-plus";
import MindMapViewer, { type MindMapTreeNode } from "@/components/MindMapViewer.vue";
import { getTaskSessions } from "@/api/studySessions";

const route = useRoute();
const router = useRouter();
const taskNum = computed(() => route.params.taskNum as string);

const loading = ref(false);
const standard = ref<StandardMindMap | null>(null);
const comparing = ref(false);
const comparingSeconds = ref(0);
let comparingTimer: ReturnType<typeof setInterval> | null = null;

const regenerating = ref(false);
const regeneratingSeconds = ref(0);
let regeneratingTimer: ReturnType<typeof setInterval> | null = null;
const lastResult = ref<any>(null);
const hasCompared = ref(false);

// 复习维度选择
const sessions = ref<{ sessionNum: string; startTime: string; expectation: string; reportCount: number; fragmentCount: number }[]>([]);
const selectedSession = ref("");
const loadingSessions = ref(false);

// 回忆输入（思维导图形式）
const recallTree = ref<MindMapTreeNode | null>(null);
const recallViewer = ref<InstanceType<typeof MindMapViewer> | null>(null);

// 标准导图展开/折叠（默认折叠，防止剧透）
const standardExpanded = ref(false);

// 编辑标准导图
const editingStandard = ref(false);
const editOutline = ref("");
const savingStandard = ref(false);
const editViewer = ref<InstanceType<typeof MindMapViewer> | null>(null);

// 回忆历史
const historyRecords = ref<RecallRecord[]>([]);
const showHistory = ref(false);

// 解析标准导图 JSON 为树节点
const standardTree = computed<MindMapTreeNode | null>(() => {
  if (!standard.value?.content) return null;
  try {
    return JSON.parse(standard.value.content) as MindMapTreeNode;
  } catch {
    return null;
  }
});

// 对比结果树（带 MATCHED/MISSED 标注）
const compareTree = computed<MindMapTreeNode | null>(() => {
  return (lastResult.value?.matchedTree as MindMapTreeNode) || null;
});

// 点击着色节点跳转原文
const goToNodeSource = (node: { sourceType: string; sourceId: number }) => {
  if (node.sourceType === "REPORT" || node.sourceType === "FRAGMENT") {
    router.push(`/review/detail/${node.sourceType.toLowerCase()}/${node.sourceId}`);
  }
};

// 格式化覆盖率
const ratioPercent = computed(() => {
  if (!lastResult.value?.recallRatio) return "0%";
  return `${(lastResult.value.recallRatio * 100).toFixed(1)}%`;
});

/** 回忆导图的初始根节点（只给根主题，内容凭记忆补全） */
const buildEmptyRecallTree = (): MindMapTreeNode => ({
  title: standard.value?.title || `任务 ${taskNum.value}`,
  children: [],
});

/** 将缩进大纲文本解析为树（兼容 "- " 前缀与 ├└│─ 等装饰符） */
const parseOutlineToTree = (text: string): MindMapTreeNode | null => {
  const lines = (text || "").split(/\r?\n/).filter((l) => l.trim().length > 0);
  if (lines.length === 0) return null;
  const cleanTitle = (l: string) => l.replace(/^[\s│├└┌┐┘┬┴┼─\-*•]+/, "").trim();
  const indentOf = (l: string) => {
    const match = l.match(/^[\s│├└┌─]*/);
    const prefix = match ? match[0] : "";
    return Math.max(1, Math.floor(prefix.replace(/[^\s]/g, " ").length / 2));
  };
  const root: MindMapTreeNode = { title: cleanTitle(lines[0]), children: [] };
  const stack: { node: MindMapTreeNode; level: number }[] = [{ node: root, level: 0 }];
  for (let i = 1; i < lines.length; i++) {
    const level = indentOf(lines[i]);
    const node: MindMapTreeNode = { title: cleanTitle(lines[i]), children: [] };
    while (stack.length > 1 && stack[stack.length - 1].level >= level) stack.pop();
    stack[stack.length - 1].node.children!.push(node);
    stack.push({ node, level });
  }
  return root;
};

// 加载数据
const loadData = async () => {
  loading.value = true;
  try {
    const res = await getStandardMindMap(taskNum.value);
    standard.value = res?.data || null;
  } catch (e: any) {
    standard.value = null;
  } finally {
    loading.value = false;
    if (!recallTree.value) {
      recallTree.value = buildEmptyRecallTree();
    }
  }
};

// 重新生成（防抖 + 用户编辑时弹窗选模式）
const handleRegenerate = async () => {
  // 防抖：正在生成中跳过
  if (regenerating.value) return;

  let mode: "full" | "incremental" = "full";

  // 如果用户编辑过，弹窗选择生成模式
  if (standard.value?.generator === "USER" || standard.value?.generator === "USER_MERGE") {
    try {
      await ElMessageBox.confirm(
        "检测到您已编辑过标准思维导图，请选择重新生成方式：",
        "重新生成",
        {
          confirmButtonText: "全量重新生成",
          cancelButtonText: "增量更新（保留编辑）",
          type: "warning",
          distinguishCancelAndClose: true,
        }
      );
      // confirm → 全量（保持 mode = "full"）
    } catch (e: any) {
      if (e === "cancel" || e?.toString()?.includes("cancel")) {
        mode = "incremental";
      } else {
        return; // 点 X 关闭 → 不做操作
      }
    }
  } else {
    // 未编辑过的简单确认
    try {
      await ElMessageBox.confirm("重新生成将从学习数据中重新生成标准思维导图，确定？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "info",
      });
    } catch {
      return;
    }
  }

  // 开始生成
  regenerating.value = true;
  regeneratingSeconds.value = 0;
  regeneratingTimer = setInterval(() => { regeneratingSeconds.value++; }, 1000);
  try {
    const res = await regenerateStandardMindMap(taskNum.value, mode);
    standard.value = res?.data || null;
    ElMessage.success(mode === "incremental" ? "标准思维导图已增量更新" : "标准思维导图已重新生成");
  } catch (e: any) {
    ElMessage.error(e.message || "重新生成失败");
  } finally {
    regenerating.value = false;
    if (regeneratingTimer) { clearInterval(regeneratingTimer); regeneratingTimer = null; }
  }
};

// 提交回忆对比
const handleRecallCompare = async () => {
  const outline = recallViewer.value?.toOutline() || "";
  if (outline.split(/\r?\n/).filter((l) => l.trim()).length <= 1) {
    ElMessage.warning("请先在回忆导图中添加节点（选中节点后按 Tab 加子节点）");
    return;
  }
  comparing.value = true;
  comparingSeconds.value = 0;
  comparingTimer = setInterval(() => { comparingSeconds.value++; }, 1000);
  try {
    const res = await recallCompare(taskNum.value, outline, selectedSession.value || undefined);
    standard.value = res?.data || null;
    hasCompared.value = true;
    // 解析对比结果
    if (standard.value) {
      const recordRes = await listRecallRecords(taskNum.value);
      const records: RecallRecord[] = recordRes?.data || [];
      if (records.length > 0) {
        const latest = records[0];
        try {
          lastResult.value = JSON.parse(latest.compareResult);
        } catch {
          lastResult.value = null;
        }
        historyRecords.value = records;
      }
    }
    ElMessage.success("回忆对比完成");
  } catch (e: any) {
    ElMessage.error(e.message || "对比失败");
  } finally {
    comparing.value = false;
    if (comparingTimer) { clearInterval(comparingTimer); comparingTimer = null; }
  }
};

// 清空重写
const resetRecall = () => {
  recallTree.value = buildEmptyRecallTree();
};

// 编辑标准导图
const startEditStandard = () => {
  editOutline.value = standard.value?.outline || "";
  editingStandard.value = true;
};

const saveStandardEdit = async () => {
  if (!editOutline.value.trim()) {
    ElMessage.warning("大纲不可为空");
    return;
  }
  savingStandard.value = true;
  try {
    const res = await updateStandardMindMap(taskNum.value, editOutline.value);
    standard.value = res?.data || null;
    editingStandard.value = false;
    ElMessage.success("标准思维导图已更新");
  } catch (e: any) {
    ElMessage.error(e.message || "保存失败");
  } finally {
    savingStandard.value = false;
  }
};

// 从导图编辑器导出大纲并保存
const saveStandardEditFromViewer = async () => {
  const outline = editViewer.value?.toOutline() || "";
  if (!outline.trim()) {
    ElMessage.warning("导图内容不可为空");
    return;
  }
  editOutline.value = outline;
  await saveStandardEdit();
};

const cancelStandardEdit = () => {
  editingStandard.value = false;
  editOutline.value = "";
};

// 查看回忆历史
const loadHistory = async () => {
  try {
    const res = await listRecallRecords(taskNum.value);
    historyRecords.value = res?.data || [];
    showHistory.value = true;
  } catch {
    ElMessage.error("加载历史记录失败");
  }
};

// 选择历史记录查看结果
const selectHistoryRecord = (record: RecallRecord) => {
  try {
    lastResult.value = JSON.parse(record.compareResult);
    // 将历史回忆内容还原到导图输入区
    const tree = parseOutlineToTree(record.recallContent);
    if (tree) recallTree.value = tree;
    hasCompared.value = true;
  } catch {
    ElMessage.error("解析对比记录失败");
  }
};

// 跳转到复习详情
const goToReviewDetail = (sourceType: string, sourceId: number) => {
  router.push(`/review/detail/${sourceType.toLowerCase()}/${sourceId}`);
};

// 获取遗漏项列表
const missedItems = computed(() => {
  if (!lastResult.value?.matchedTree) return [];
  const items: { title: string; sourceType: string; sourceId: number }[] = [];
  const walk = (node: any) => {
    const notes = node.notes || "";
    if (notes.startsWith("MISSED|")) {
      items.push({
        title: node.title || "",
        sourceType: node.sourceType || "",
        sourceId: node.sourceId,
      });
    }
    (node.children || []).forEach(walk);
  };
  walk(lastResult.value.matchedTree);
  return items;
});

// 额外节点列表
const extraNodes = computed(() => {
  const raw = lastResult.value?.extraNodes || [];
  // 兼容字符串数组和对象数组两种格式
  return raw.map((item: any) => typeof item === "string" ? { title: item } : item);
});

// 加载会话列表（复习维度选择器用）
const loadSessions = async () => {
  loadingSessions.value = true;
  try {
    const res = await getTaskSessions(taskNum.value);
    sessions.value = res?.data || [];
  } catch {
    sessions.value = [];
  } finally {
    loadingSessions.value = false;
  }
};

// 格式化会话标签
const formatSessionLabel = (s: { sessionNum: string; startTime: string; expectation: string; reportCount: number; fragmentCount: number }) => {
  const date = s.startTime ? s.startTime.replace("T", " ").substring(0, 16) : s.sessionNum;
  const hint = s.expectation ? s.expectation.substring(0, 30) : "";
  return `${date} ${hint ? "— " + hint : ""}`;
};

onMounted(() => {
  loadData();
  loadSessions();
});
</script>

<template>
  <section class="recall-page">
    <!-- 顶部操作栏 -->
    <div class="page-header">
      <el-button size="small" @click="router.back()">← 返回</el-button>
      <h2>回忆复习</h2>
      <el-button size="small" @click="loadHistory" v-if="!showHistory">
        历史记录
      </el-button>
    </div>

    <!-- 复习维度选择器 -->
    <div class="review-scope surface-card" v-if="sessions.length > 0 || loadingSessions">
      <span class="scope-label">复习范围</span>
      <el-select v-model="selectedSession" placeholder="选择复习范围" clearable size="small" :loading="loadingSessions">
        <el-option label="全部任务" value="" />
        <el-option
          v-for="s in sessions"
          :key="s.sessionNum"
          :label="formatSessionLabel(s)"
          :value="s.sessionNum"
        />
      </el-select>
      <el-tag v-if="selectedSession" size="small" type="success" effect="light">
        已过滤：仅匹配该会话知识点
      </el-tag>
      <span v-else-if="!selectedSession" class="scope-hint">不过滤，对比全部标准导图</span>
    </div>

    <!-- 统计卡片 -->
    <div class="stats-card surface-card" v-if="hasCompared && lastResult">
      <div class="stat-item">
        <span class="stat-label">回忆覆盖率</span>
        <strong class="stat-value highlight">{{ ratioPercent }}</strong>
      </div>
      <div class="stat-item">
        <span class="stat-label">✅ 回忆命中</span>
        <strong class="stat-value matched">{{ lastResult.matchedCount }}</strong>
      </div>
      <div class="stat-item">
        <span class="stat-label">❌ 遗漏</span>
        <strong class="stat-value missed">{{ lastResult.missedCount }}</strong>
      </div>
      <div class="stat-item">
        <span class="stat-label">➕ 额外</span>
        <strong class="stat-value extra">{{ lastResult.extraCount }}</strong>
      </div>
    </div>

    <!-- 回忆历史 -->
    <article class="surface-card" v-if="showHistory && historyRecords.length > 0">
      <h3>回忆历史</h3>
      <div class="history-list">
        <div
          v-for="record in historyRecords"
          :key="record.id"
          class="history-item"
          @click="selectHistoryRecord(record)"
        >
          <span class="history-time">{{ record.createdTime?.replace("T", " ")?.substring(0, 16) }}</span>
          <el-tag v-if="record.sessionNum" size="small" type="success" effect="plain" class="session-badge">会话</el-tag>
          <el-tag v-else size="small" type="info" effect="plain" class="session-badge">全部</el-tag>
          <span class="history-ratio">覆盖率 {{ (record.recallRatio * 100).toFixed(1) }}%</span>
          <span class="history-detail">✅{{ record.matchedCount }} ❌{{ record.missedCount }} ➕{{ record.extraCount }}</span>
        </div>
      </div>
    </article>

    <!-- 回忆输入：可编辑思维导图 -->
    <article class="surface-card recall-panel">
      <div class="panel-header">
        <h3>🧠 你的回忆</h3>
        <div class="panel-actions">
          <el-button type="success" :loading="comparing" @click="handleRecallCompare">
            提交对比
          </el-button>
          <el-button v-if="hasCompared" @click="resetRecall">
            清空重写
          </el-button>
        </div>
        <p v-if="comparing" class="ai-waiting">
          <template v-if="comparingSeconds < 3">正在提交 AI 任务…</template>
          <template v-else-if="comparingSeconds < 60">AI 对比分析中，已等待 {{ comparingSeconds }} 秒，请稍候…</template>
          <template v-else-if="comparingSeconds < 180">内容较多，AI 正在深入分析，已等待 {{ comparingSeconds }} 秒…</template>
          <template v-else>即将完成，已等待 {{ comparingSeconds }} 秒，请耐心等待…</template>
        </p>
      </div>
      <p class="panel-hint">
        凭记忆在导图上补全该任务的知识点：选中节点后 Tab 加子节点、Enter 加同级节点、双击修改文字。
      </p>
      <MindMapViewer ref="recallViewer" :tree="recallTree" :editable="true" height="60vh" />
    </article>

    <!-- 标准导图（含对比着色） -->
    <article class="surface-card standard-panel">
      <div class="panel-header">
        <h3>📖 标准思维导图</h3>
        <div class="panel-actions">
          <el-button size="small" @click="standardExpanded = !standardExpanded">
            {{ standardExpanded ? "折叠" : "展开" }}
          </el-button>
          <el-button
            v-if="standardExpanded"
            size="small"
            type="warning"
            :loading="regenerating"
            @click="handleRegenerate"
          >
            重新生成
          </el-button>
          <el-button
            v-if="standardExpanded && !editingStandard"
            size="small"
            type="primary"
            @click="startEditStandard"
          >
            编辑
          </el-button>
        </div>
        <p v-if="regenerating" class="ai-waiting" style="margin-top: 4px; width: 100%;">
          <template v-if="regeneratingSeconds < 3">正在准备生成…</template>
          <template v-else>AI 正在生成中，已等待 {{ regeneratingSeconds }} 秒，请稍候…</template>
        </p>
      </div>

      <div v-if="!standard" class="empty-state">
        <el-empty description="暂无标准思维导图" :image-size="64">
          <el-button type="success" :loading="loading" @click="loadData">
            生成
          </el-button>
        </el-empty>
      </div>

      <div v-else-if="editingStandard" class="edit-area">
        <p class="panel-hint">直接在导图上编辑（Tab 加子节点 / Enter 加同级 / 双击改文字），保存后生效。</p>
        <MindMapViewer ref="editViewer" :tree="standardTree" :editable="true" height="60vh" />
        <div class="edit-actions">
          <el-button @click="cancelStandardEdit">取消</el-button>
          <el-button type="success" :loading="savingStandard" @click="saveStandardEditFromViewer">
            保存更新
          </el-button>
        </div>
      </div>

      <div v-else-if="standardExpanded" class="standard-content">
        <div class="standard-meta">
          <span>来源：{{ standard.generator }}</span>
          <span>参考：{{ standard.sourceReportCount }} 份报告 + {{ standard.sourceFragmentCount }} 份残片</span>
        </div>
        <MindMapViewer
          v-if="standardTree"
          :tree="compareTree || standardTree"
          :color-by-compare="!!compareTree"
          height="60vh"
          @node-click="goToNodeSource"
        />
        <pre v-else class="standard-outline">{{ standard.outline || standard.content }}</pre>
        <p v-if="standard.summary" class="generator-info">{{ standard.summary }}</p>
      </div>

      <div v-else class="collapsed-hint">
        <p>标准导图已生成。展开后可查看或编辑。建议先凭记忆补全回忆导图再对照。</p>
      </div>
    </article>

    <!-- 遗漏项 + 额外项详情 -->
    <div v-if="hasCompared && lastResult" class="detail-section">
      <!-- 遗漏项 -->
      <article class="surface-card" v-if="missedItems.length > 0">
        <h3>❌ 遗漏的知识点</h3>
        <div class="missed-list">
          <div v-for="(item, idx) in missedItems" :key="idx" class="missed-item">
            <span class="missed-title">{{ item.title }}</span>
            <el-button
              v-if="item.sourceType && item.sourceId"
              text
              type="primary"
              size="small"
              @click="goToReviewDetail(item.sourceType, item.sourceId)"
            >
              查看原文
            </el-button>
          </div>
        </div>
      </article>

      <!-- 额外项 -->
      <article class="surface-card" v-if="extraNodes.length > 0">
        <h3>➕ 你额外回忆到的知识点</h3>
        <div class="extra-list">
          <div v-for="(item, idx) in extraNodes" :key="idx" class="extra-item">
            {{ item.title }}
          </div>
        </div>
      </article>
    </div>
  </section>
</template>

<style scoped>
.recall-page {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.page-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.page-header h2 {
  margin: 0;
  flex: 1;
  color: var(--green-900);
  font-size: 18px;
}

.surface-card {
  padding: 20px 22px;
  background: #fff;
  border-radius: 8px;
  border: 1px solid var(--border-soft, #e0e0e0);
}

.surface-card h3 {
  margin: 0 0 8px;
  color: var(--green-900);
  font-size: 16px;
}

.stats-card {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  background: linear-gradient(135deg, #f1f8e9 0%, #e8f5e9 100%);
}

.stat-item {
  min-width: 100px;
}

.stat-label {
  display: block;
  font-size: 12px;
  color: var(--text-secondary, #666);
}

.stat-value {
  display: block;
  font-size: 28px;
  margin-top: 4px;
}

.highlight { color: #2e7d32; }
.matched { color: #2e7d32; }
.missed { color: #c62828; }
.extra { color: #1565c0; }

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.panel-header h3 {
  margin: 0;
}

.panel-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
  flex-wrap: wrap;
}

.panel-hint {
  font-size: 13px;
  color: var(--text-secondary, #666);
  margin: 0 0 12px;
  line-height: 1.5;
}

.ai-waiting {
  font-size: 13px;
  color: #e6a23c;
  margin: 4px 0 0;
  display: flex;
  align-items: center;
  gap: 6px;
}

.ai-waiting::before {
  content: "";
  width: 14px;
  height: 14px;
  border: 2px solid #f3d19e;
  border-top-color: #e6a23c;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.standard-meta {
  display: flex;
  gap: 12px;
  font-size: 12px;
  color: var(--text-secondary, #666);
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.standard-outline {
  white-space: pre-wrap;
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-primary, #333);
  background: #fafafa;
  padding: 12px;
  border-radius: 6px;
  border: 1px solid var(--border-soft, #e0e0e0);
  max-height: 400px;
  overflow-y: auto;
  word-break: break-word;
}

.generator-info {
  font-size: 12px;
  color: var(--text-secondary, #666);
  margin: 8px 0 0;
}

.collapsed-hint {
  color: var(--text-secondary, #666);
  font-size: 14px;
  text-align: center;
  padding: 20px;
}

.empty-state {
  display: flex;
  justify-content: center;
}

.edit-area {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.detail-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  align-items: start;
}

@media (max-width: 900px) {
  .detail-section {
    grid-template-columns: 1fr;
  }
}

.detail-section h3 {
  margin: 0 0 12px;
  color: var(--green-900);
  font-size: 15px;
}

.missed-list,
.extra-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.missed-item,
.extra-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  background: #fafafa;
  font-size: 14px;
}

.missed-item {
  border-left: 3px solid #c62828;
}

.extra-item {
  border-left: 3px solid #1565c0;
}

.missed-title {
  flex: 1;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.history-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  transition: background 0.15s;
}

.history-item:hover {
  background: #f1f8e9;
}

.history-time {
  color: var(--text-secondary, #666);
  min-width: 120px;
}

.history-ratio {
  font-weight: 600;
  color: var(--green-800);
  min-width: 80px;
}

.history-detail {
  color: var(--text-secondary, #666);
}

/* 复习范围选择器 */
.review-scope {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 22px;
}

.scope-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--green-800);
  white-space: nowrap;
}

.scope-hint {
  font-size: 12px;
  color: var(--text-secondary, #999);
}

.session-badge {
  flex-shrink: 0;
}
</style>
