<script setup lang="ts">
import { ElMessage, ElMessageBox } from "element-plus";
import type { InputInstance } from "element-plus";
import { computed, nextTick, onMounted, reactive, ref } from "vue";

import { api } from "../services/api";
import type {
  ContentGenerationConfigDetail,
  ContentGenerationHistoryItem,
  ContentGenerationType,
} from "../types/api";
import AdminPagination from "./AdminPagination.vue";

const activeType = ref<ContentGenerationType>("help_card");
const loading = ref(false);
const saving = ref(false);
const previewing = ref(false);
const testing = ref(false);
const detailLoading = ref(false);
const current = ref<ContentGenerationConfigDetail | null>(null);
const history = ref<ContentGenerationHistoryItem[]>([]);
const historyTotal = ref(0);
const historyPage = ref(1);
const historyPageSize = ref(10);
const previewContent = ref("");
const testUsedFallback = ref(false);
const selectedHistory = ref<ContentGenerationConfigDetail | null>(null);
const historyDialogOpen = ref(false);
const templateInputRef = ref<InputInstance>();
const form = reactive({ templateContent: "", instructionContent: "" });
const saved = reactive({ templateContent: "", instructionContent: "" });
const sampleText = ref(
  "我第一次参加带练，不太确定练习顺序。做到一半身体有些紧，我会担心自己是不是做错了，想请老师确认什么时候应该暂停。",
);

const dirty = computed(
  () => form.templateContent !== saved.templateContent || form.instructionContent !== saved.instructionContent,
);
const typeLabel = computed(() => activeType.value === "help_card" ? "老师求助卡" : "班级分享稿");

onMounted(loadAll);

async function loadAll() {
  loading.value = true;
  try {
    const [config, page] = await Promise.all([
      api.contentGenerationConfig(activeType.value),
      api.contentGenerationHistory(activeType.value, { page: historyPage.value, pageSize: historyPageSize.value }),
    ]);
    applyConfig(config);
    history.value = page.items;
    historyTotal.value = page.total;
    await refreshPreview();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "内容生成配置加载失败");
  } finally {
    loading.value = false;
  }
}

function applyConfig(config: ContentGenerationConfigDetail) {
  current.value = config;
  form.templateContent = config.templateContent;
  form.instructionContent = config.instructionContent;
  saved.templateContent = config.templateContent;
  saved.instructionContent = config.instructionContent;
}

async function switchType(type: ContentGenerationType) {
  if (type === activeType.value) return;
  if (dirty.value) {
    try {
      await ElMessageBox.confirm("当前修改尚未保存，切换后将丢失。确定继续吗？", "切换配置", {
        confirmButtonText: "继续切换",
        cancelButtonText: "留在当前页",
        type: "warning",
      });
    } catch {
      return;
    }
  }
  activeType.value = type;
  historyPage.value = 1;
  previewContent.value = "";
  testUsedFallback.value = false;
  await loadAll();
}

async function insertVariable(name: string) {
  const token = `{{${name}}}`;
  const textarea = templateInputRef.value?.textarea;
  if (!textarea) {
    form.templateContent = `${form.templateContent}${form.templateContent.endsWith("\n") ? "" : "\n"}${token}`;
    return;
  }
  const start = textarea.selectionStart ?? form.templateContent.length;
  const end = textarea.selectionEnd ?? start;
  form.templateContent = `${form.templateContent.slice(0, start)}${token}${form.templateContent.slice(end)}`;
  await nextTick();
  textarea.focus();
  textarea.setSelectionRange(start + token.length, start + token.length);
}

function variableToken(name: string) {
  return `{{${name}}}`;
}

async function refreshPreview() {
  previewing.value = true;
  try {
    const result = await api.previewContentGeneration({
      configType: activeType.value,
      templateContent: form.templateContent,
    });
    previewContent.value = result.content;
    testUsedFallback.value = false;
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "预览生成失败");
  } finally {
    previewing.value = false;
  }
}

async function testGeneration() {
  testing.value = true;
  try {
    const result = await api.testContentGeneration({
      configType: activeType.value,
      templateContent: form.templateContent,
      instructionContent: form.instructionContent,
      sampleText: sampleText.value,
    });
    previewContent.value = result.content;
    testUsedFallback.value = result.usedFallback;
    ElMessage.success(result.usedFallback ? "模型结果不可用，已展示安全回退结果" : "AI 整理测试完成");
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "AI 整理测试失败");
  } finally {
    testing.value = false;
  }
}

async function saveConfig() {
  if (!dirty.value || saving.value) return;
  saving.value = true;
  try {
    const config = await api.saveContentGenerationConfig(activeType.value, {
      templateContent: form.templateContent,
      instructionContent: form.instructionContent,
    });
    applyConfig(config);
    ElMessage.success("已保存并立即发布为新版本");
    historyPage.value = 1;
    await loadHistory();
    await refreshPreview();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "配置保存失败");
  } finally {
    saving.value = false;
  }
}

async function resetConfig() {
  try {
    await ElMessageBox.confirm(
      `确定将${typeLabel.value}恢复为系统默认配置吗？系统会保留当前版本，可随时回滚。`,
      "恢复默认配置",
      { confirmButtonText: "恢复默认", cancelButtonText: "取消", type: "warning" },
    );
    saving.value = true;
    const config = await api.resetContentGenerationConfig(activeType.value);
    applyConfig(config);
    historyPage.value = 1;
    await loadHistory();
    await refreshPreview();
    ElMessage.success("已恢复默认配置");
  } catch (error) {
    if (error instanceof Error) ElMessage.error(error.message);
  } finally {
    saving.value = false;
  }
}

async function loadHistory() {
  const page = await api.contentGenerationHistory(activeType.value, {
    page: historyPage.value,
    pageSize: historyPageSize.value,
  });
  history.value = page.items;
  historyTotal.value = page.total;
}

async function changeHistoryPagination(page: number, pageSize: number) {
  historyPage.value = page;
  historyPageSize.value = pageSize;
  await loadHistory();
}

async function openHistory(item: ContentGenerationHistoryItem) {
  historyDialogOpen.value = true;
  detailLoading.value = true;
  selectedHistory.value = null;
  try {
    selectedHistory.value = await api.contentGenerationHistoryDetail(activeType.value, item.id);
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "历史版本加载失败");
    historyDialogOpen.value = false;
  } finally {
    detailLoading.value = false;
  }
}

async function restoreHistory(id: number) {
  try {
    await ElMessageBox.confirm("确定回滚到这个版本吗？回滚会生成一个新版本，不会覆盖历史记录。", "回滚配置", {
      confirmButtonText: "确认回滚",
      cancelButtonText: "取消",
      type: "warning",
    });
    saving.value = true;
    const config = await api.restoreContentGenerationConfig(activeType.value, id);
    applyConfig(config);
    historyDialogOpen.value = false;
    historyPage.value = 1;
    await loadHistory();
    await refreshPreview();
    ElMessage.success("已回滚并发布为新版本");
  } catch (error) {
    if (error instanceof Error) ElMessage.error(error.message);
  } finally {
    saving.value = false;
  }
}

function formatTime(value?: string | null) {
  if (!value) return "系统默认";
  return new Date(value).toLocaleString("zh-CN", { hour12: false });
}

function changeTypeLabel(value: string) {
  return { save: "保存", reset: "恢复默认", restore: "历史回滚", default: "系统默认" }[value] || value;
}
</script>

<template>
  <div v-loading="loading" class="content-generation-page">
    <div class="page-head inline">
      <div>
        <h2>内容生成配置</h2>
        <p>管理求助卡和分享稿的模板与 AI 整理规则；每次保存立即生效，并自动保留可回滚版本。</p>
      </div>
      <div class="config-head-actions">
        <el-button :loading="previewing" @click="refreshPreview">刷新预览</el-button>
        <el-button type="primary" :loading="saving" :disabled="!dirty" @click="saveConfig">保存并发布新版本</el-button>
      </div>
    </div>

    <nav class="content-type-tabs" aria-label="内容生成类型">
      <button type="button" :class="{ active: activeType === 'help_card' }" @click="switchType('help_card')">
        <strong>老师求助卡</strong><span>给老师确认方向，不会自动转人工</span>
      </button>
      <button type="button" :class="{ active: activeType === 'share_draft' }" @click="switchType('share_draft')">
        <strong>班级分享稿</strong><span>用户自行核对、复制和分享</span>
      </button>
    </nav>

    <section class="generation-editor-layout">
      <div class="generation-editor-column">
        <article class="generation-panel">
          <header>
            <div><h3>卡片模板</h3><p>点击变量可添加到模板；未知变量或缺少必要变量时不能发布。</p></div>
            <el-button text :disabled="saving" @click="resetConfig">恢复系统默认</el-button>
          </header>
          <div class="variable-list">
            <button v-for="item in current?.variables || []" :key="item.name" type="button" @click="insertVariable(item.name)">
              {{ item.label }} <code>{{ variableToken(item.name) }}</code>
            </button>
          </div>
          <el-input ref="templateInputRef" v-model="form.templateContent" type="textarea" :rows="18" resize="vertical" />
          <small>{{ form.templateContent.length }}/20000 字符</small>
        </article>

        <article class="generation-panel">
          <header><div><h3>AI 整理规则</h3><p>只控制如何提炼本次材料，不会修改 Agent 主提示词和知识库检索规则。</p></div></header>
          <el-input v-model="form.instructionContent" type="textarea" :rows="7" resize="vertical" />
          <small>{{ form.instructionContent.length }}/10000 字符</small>
        </article>

        <article class="locked-rules">
          <strong>系统锁定的安全提醒</strong>
          <p>{{ current?.lockedFooter }}</p>
          <small>这段内容会由系统固定追加，管理员不能删除，避免卡片被误解为已经转人工或自动发送。</small>
        </article>
      </div>

      <aside class="generation-preview-column">
        <article class="generation-panel preview-panel">
          <header><div><h3>实际效果预览</h3><p>预览始终包含系统锁定的安全提醒。</p></div></header>
          <pre>{{ previewContent || "点击“刷新预览”查看效果" }}</pre>
          <el-alert v-if="testUsedFallback" title="本次测试使用了安全回退结果，模型未返回有效结构化内容。" type="warning" :closable="false" show-icon />
        </article>

        <article class="generation-panel test-panel">
          <header><div><h3>AI 整理测试</h3><p>填写一段模拟用户表达，测试当前规则和模板，不会保存为正式卡片。</p></div></header>
          <el-input v-model="sampleText" type="textarea" :rows="7" resize="vertical" maxlength="20000" show-word-limit />
          <el-button type="primary" plain :loading="testing" @click="testGeneration">测试 AI 整理效果</el-button>
        </article>
      </aside>
    </section>

    <section class="generation-history generation-panel">
      <header>
        <div><h3>版本记录</h3><p>当前配置：{{ current?.updatedByName }} · {{ formatTime(current?.updatedAt) }}</p></div>
        <el-tag v-if="current" type="success">{{ changeTypeLabel(current.changeType) }}</el-tag>
      </header>
      <el-empty v-if="!history.length" description="尚未保存过版本，当前使用系统默认配置" :image-size="72" />
      <div v-else class="generation-history-list">
        <article v-for="item in history" :key="item.id" :class="{ current: item.isCurrent }">
          <div>
            <strong>版本 #{{ item.id }} <el-tag v-if="item.isCurrent" size="small" type="success">当前</el-tag></strong>
            <p>{{ item.preview }}</p>
            <small>{{ changeTypeLabel(item.changeType) }} · {{ item.updatedByName }} · {{ formatTime(item.updatedAt) }}</small>
          </div>
          <el-button @click="openHistory(item)">查看</el-button>
        </article>
      </div>
      <AdminPagination
        v-if="historyTotal > 0"
        :page="historyPage"
        :page-size="historyPageSize"
        :total="historyTotal"
        @change="changeHistoryPagination"
      />
    </section>

    <el-dialog v-model="historyDialogOpen" title="内容生成配置历史版本" width="min(760px, 92vw)" append-to-body>
      <div v-loading="detailLoading" class="generation-history-detail">
        <template v-if="selectedHistory">
          <dl>
            <div><dt>版本</dt><dd>#{{ selectedHistory.id }}</dd></div>
            <div><dt>操作</dt><dd>{{ changeTypeLabel(selectedHistory.changeType) }}</dd></div>
            <div><dt>操作人</dt><dd>{{ selectedHistory.updatedByName }}</dd></div>
            <div><dt>时间</dt><dd>{{ formatTime(selectedHistory.updatedAt) }}</dd></div>
          </dl>
          <h4>卡片模板</h4><pre>{{ selectedHistory.templateContent }}</pre>
          <h4>AI 整理规则</h4><pre>{{ selectedHistory.instructionContent }}</pre>
        </template>
      </div>
      <template #footer>
        <el-button @click="historyDialogOpen = false">关闭</el-button>
        <el-button v-if="selectedHistory" type="primary" :loading="saving" @click="restoreHistory(selectedHistory.id!)">回滚到此版本</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.content-generation-page { display: grid; gap: 18px; }
.config-head-actions { display: flex; gap: 10px; }
.content-type-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.content-type-tabs button { min-height: 78px; display: grid; gap: 5px; padding: 15px 18px; border: 1px solid #dfe8e4; border-radius: 16px; background: #fff; color: #65746f; text-align: left; transition: border-color .18s ease, background .18s ease, transform .18s ease; }
.content-type-tabs button:hover { border-color: #91c8b5; transform: translateY(-1px); }
.content-type-tabs button.active { border-color: #43a783; background: #eff8f4; color: #176c51; box-shadow: 0 8px 24px rgba(23, 108, 81, .08); }
.content-type-tabs strong { font-size: 16px; }
.content-type-tabs span { font-size: 12px; }
.generation-editor-layout { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(360px, .85fr); gap: 16px; align-items: start; }
.generation-editor-column, .generation-preview-column { min-width: 0; display: grid; gap: 16px; }
.generation-panel, .locked-rules { padding: 18px; border: 1px solid #dfe8e4; border-radius: 16px; background: #fff; }
.generation-panel > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
.generation-panel h3 { margin: 0; color: #1d342d; font-size: 17px; }
.generation-panel header p { margin: 5px 0 0; color: #75847f; font-size: 12px; line-height: 1.6; }
.generation-panel > small { display: block; margin-top: 7px; color: #8a9893; font-size: 11px; text-align: right; }
.variable-list { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.variable-list button { padding: 6px 9px; border: 1px solid #d8e6e0; border-radius: 9px; background: #f7faf9; color: #49665c; font-size: 12px; }
.variable-list button:hover { border-color: #62b596; background: #edf7f3; }
.variable-list code { margin-left: 3px; color: #17805f; font-size: 11px; }
.locked-rules { border-color: #e9dfbd; background: #fffaf0; }
.locked-rules strong { color: #705d2e; }
.locked-rules p { margin: 9px 0 4px; color: #655b43; font-size: 13px; line-height: 1.75; white-space: pre-wrap; }
.locked-rules small { color: #8c805f; font-size: 11px; }
.preview-panel { position: sticky; top: 18px; }
.preview-panel pre, .generation-history-detail pre { max-height: 520px; overflow: auto; margin: 0; padding: 16px; border: 1px solid #e3ebe8; border-radius: 13px; background: #f8fbfa; color: #324b43; font: inherit; font-size: 13px; line-height: 1.8; white-space: pre-wrap; }
.preview-panel .el-alert { margin-top: 12px; }
.test-panel .el-button { width: 100%; margin-top: 12px; }
.generation-history-list { display: grid; gap: 10px; }
.generation-history-list article { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 14px; padding: 13px 14px; border: 1px solid #e4ebe8; border-radius: 13px; }
.generation-history-list article.current { border-color: #83c8ae; background: #f1f8f5; }
.generation-history-list article > div { min-width: 0; }
.generation-history-list strong { display: flex; align-items: center; gap: 7px; color: #2b4039; font-size: 13px; }
.generation-history-list p { overflow: hidden; margin: 5px 0; color: #64736e; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.generation-history-list small { color: #89958f; font-size: 11px; }
.generation-history-detail { min-height: 180px; }
.generation-history-detail dl { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 0 0 18px; }
.generation-history-detail dl div { padding: 10px; border-radius: 10px; background: #f5f8f7; }
.generation-history-detail dt { color: #89958f; font-size: 11px; }
.generation-history-detail dd { margin: 5px 0 0; color: #30483f; font-size: 13px; }
.generation-history-detail h4 { margin: 18px 0 8px; }
@media (max-width: 1100px) { .generation-editor-layout { grid-template-columns: 1fr; } .preview-panel { position: static; } }
@media (max-width: 720px) { .content-type-tabs { grid-template-columns: 1fr; } .config-head-actions { width: 100%; } .config-head-actions .el-button { flex: 1; } .generation-history-detail dl { grid-template-columns: 1fr 1fr; } }
</style>
