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

import { api } from "../services/api";
import type { AttentionConfig, AttentionPreviewMessage, AttentionPreviewResult } from "../types/api";
import AdminPagination from "./AdminPagination.vue";
import { formatDateTime } from "../utils/dateTime";

const props = defineProps<{ canConfig: boolean; canPreview: boolean }>();

const loading = ref(false);
const saving = ref(false);
const previewLoading = ref(false);
const previewMessages = ref<AttentionPreviewMessage[]>([]);
const selectedMessages = ref<AttentionPreviewMessage[]>([]);
const previewResults = ref<AttentionPreviewResult[]>([]);
const keyword = ref("");
const pager = reactive({ page: 1, pageSize: 20, total: 0 });
const terms = reactive({ urgent: "", important: "", normal: "" });
const config = reactive<AttentionConfig>({
  enabled: true,
  keywordEnabled: true,
  aiEnabled: false,
  knowledgeMissingEnabled: true,
  urgentTerms: [],
  importantTerms: [],
  normalTerms: [],
  promptTemplate: "",
  recognitionItems: [],
});

const canRunPreview = computed(() => props.canPreview && selectedMessages.value.length > 0 && !previewLoading.value);

onMounted(async () => {
  if (props.canConfig || props.canPreview) await loadConfig();
  if (props.canPreview) await loadPreviewMessages();
});

async function loadConfig() {
  loading.value = true;
  try {
    assignConfig(props.canConfig ? await api.attentionConfig() : await api.attentionPreviewConfig());
  } finally {
    loading.value = false;
  }
}

function assignConfig(value: AttentionConfig) {
  Object.assign(config, value);
  terms.urgent = value.urgentTerms.join("\n");
  terms.important = value.importantTerms.join("\n");
  terms.normal = value.normalTerms.join("\n");
}

function currentConfig(): AttentionConfig {
  return {
    ...config,
    urgentTerms: splitTerms(terms.urgent),
    importantTerms: splitTerms(terms.important),
    normalTerms: splitTerms(terms.normal),
  };
}

function splitTerms(value: string) {
  return [...new Set(value.split(/[\n,，]+/).map((item) => item.trim()).filter(Boolean))];
}

function addRecognitionItem() {
  if (config.recognitionItems.length >= 30) {
    ElMessage.warning("可识别项最多配置 30 个");
    return;
  }
  config.recognitionItems.push({ name: "", description: "", priority: "normal", enabled: true });
}

function removeRecognitionItem(index: number) {
  config.recognitionItems.splice(index, 1);
}

async function saveConfig() {
  saving.value = true;
  try {
    assignConfig(await api.saveAttentionConfig(currentConfig()));
    ElMessage.success("人工关注筛选规则已保存，后续新问答立即生效");
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "配置保存失败");
  } finally {
    saving.value = false;
  }
}

async function loadPreviewMessages(page = 1, pageSize = pager.pageSize) {
  previewLoading.value = true;
  try {
    const result = await api.attentionPreviewMessages({ keyword: keyword.value.trim(), page, pageSize });
    previewMessages.value = result.items;
    selectedMessages.value = [];
    Object.assign(pager, { page: result.page, pageSize: result.pageSize, total: result.total });
  } finally {
    previewLoading.value = false;
  }
}

function onSelectionChange(rows: AttentionPreviewMessage[]) {
  if (rows.length > 20) {
    ElMessage.warning("单次最多预览 20 条历史消息");
    selectedMessages.value = rows.slice(0, 20);
    return;
  }
  selectedMessages.value = rows;
}

async function runPreview() {
  if (!canRunPreview.value) return;
  previewLoading.value = true;
  try {
    previewResults.value = await api.previewAttention(
      selectedMessages.value.map((item) => item.messageId),
      currentConfig(),
    );
    ElMessage.success(`已完成 ${previewResults.value.length} 条历史消息筛选预览`);
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "提示词筛选预览失败");
  } finally {
    previewLoading.value = false;
  }
}

function priorityLabel(value: string) {
  return ({ urgent: "紧急", important: "重要", normal: "普通" } as Record<string, string>)[value] || "-";
}

function sourceLabel(value: string) {
  return ({ keyword: "关键词", knowledge_missing: "知识缺失", ai: "AI 提示词", rules: "未触发", disabled: "总开关关闭" } as Record<string, string>)[value] || value;
}
</script>

<template>
  <section v-loading="loading" class="attention-config-workspace">
    <el-alert
      title="运行顺序：紧急/重要/普通关键词 → 知识缺失 → AI 提示词。确定性规则命中后不再调用模型。"
      type="info"
      :closable="false"
      show-icon
    />

    <article v-if="canConfig" class="attention-config-card">
      <header><div><h3>自动筛选规则</h3><p>配置只影响保存后的新问答，不会自动重跑已有记录。</p></div><el-button type="primary" :loading="saving" @click="saveConfig">保存规则</el-button></header>
      <div class="attention-switch-grid">
        <label><span><strong>启用人工关注自动筛选</strong><small>关闭后不再自动创建新的关注记录</small></span><el-switch v-model="config.enabled" /></label>
        <label><span><strong>启用关键词筛选</strong><small>优先执行，不产生模型调用费用</small></span><el-switch v-model="config.keywordEnabled" /></label>
        <label><span><strong>知识缺失自动关注</strong><small>知识库应答缺少可靠正式知识时触发</small></span><el-switch v-model="config.knowledgeMissingEnabled" /></label>
        <label><span><strong>启用 AI 提示词筛选</strong><small>仅在前面规则未命中时异步执行，不会拖慢用户收到回答</small></span><el-switch v-model="config.aiEnabled" /></label>
      </div>
      <div class="attention-term-grid">
        <label><strong>紧急关键词</strong><small>每行一个，命中后标记为紧急</small><el-input v-model="terms.urgent" type="textarea" :rows="6" /></label>
        <label><strong>重要关键词</strong><small>每行一个，命中后标记为重要</small><el-input v-model="terms.important" type="textarea" :rows="6" /></label>
        <label><strong>普通关键词</strong><small>每行一个，命中后标记为普通</small><el-input v-model="terms.normal" type="textarea" :rows="6" /></label>
      </div>
      <section class="recognition-item-editor">
        <header><span><strong>AI 可识别项</strong><small>语义筛选只会从已启用项目中选择；可按业务需要继续增加。</small></span><el-button @click="addRecognitionItem">新增可识别项</el-button></header>
        <el-table :data="config.recognitionItems" border>
          <el-table-column label="启用" width="72"><template #default="{ row }"><el-switch v-model="row.enabled" /></template></el-table-column>
          <el-table-column label="项目名称" width="180"><template #default="{ row }"><el-input v-model="row.name" maxlength="50" placeholder="例如：疑似投诉" /></template></el-table-column>
          <el-table-column label="识别说明" min-width="360"><template #default="{ row }"><el-input v-model="row.description" maxlength="500" placeholder="说明什么情况下算命中，尽量写清边界" /></template></el-table-column>
          <el-table-column label="优先级" width="130"><template #default="{ row }"><el-select v-model="row.priority"><el-option label="紧急" value="urgent" /><el-option label="重要" value="important" /><el-option label="普通" value="normal" /></el-select></template></el-table-column>
          <el-table-column label="操作" width="80"><template #default="{ $index }"><el-button link type="danger" @click="removeRecognitionItem($index)">删除</el-button></template></el-table-column>
        </el-table>
      </section>
      <label class="attention-prompt-editor">
        <span><strong>AI 筛选提示词</strong><small>系统会自动追加历史问答数据、安全边界和固定 JSON 输出格式，无需在提示词中写变量。</small></span>
        <el-input v-model="config.promptTemplate" type="textarea" :rows="12" maxlength="8000" show-word-limit />
      </label>
    </article>

    <article v-if="canPreview" class="attention-config-card">
      <header><div><h3>历史消息筛选预览</h3><p>可使用当前页面尚未保存的关键词和提示词运行，不会创建人工关注记录。</p></div><el-button type="primary" :loading="previewLoading" :disabled="!canRunPreview" @click="runPreview">预览选中消息</el-button></header>
      <div class="attention-preview-search"><el-input v-model="keyword" clearable placeholder="搜索历史问题、用户姓名或手机号" @keyup.enter="loadPreviewMessages(1)" /><el-button @click="loadPreviewMessages(1)">查询</el-button><span>已选 {{ selectedMessages.length }}/20</span></div>
      <el-table :data="previewMessages" stripe @selection-change="onSelectionChange">
        <el-table-column type="selection" width="48" />
        <el-table-column prop="question" label="历史问题" min-width="280" show-overflow-tooltip />
        <el-table-column prop="userName" label="用户" width="120" />
        <el-table-column prop="sessionTitle" label="会话" min-width="180" show-overflow-tooltip />
        <el-table-column label="知识缺失" width="100"><template #default="{ row }"><el-tag :type="row.knowledgeMissing ? 'warning' : 'info'">{{ row.knowledgeMissing ? "是" : "否" }}</el-tag></template></el-table-column>
        <el-table-column label="提问时间" width="180"><template #default="{ row }">{{ formatDateTime(row.createdAt) }}</template></el-table-column>
      </el-table>
      <AdminPagination :page="pager.page" :page-size="pager.pageSize" :total="pager.total" @change="loadPreviewMessages" />
    </article>

    <article v-if="previewResults.length" class="attention-config-card preview-result-card">
      <header><div><h3>筛选结果</h3><p>结果仅供调整规则和提示词，不会写入关注记录。</p></div></header>
      <el-table :data="previewResults" stripe>
        <el-table-column label="结果" width="100"><template #default="{ row }"><el-tag :type="row.needsAttention ? 'danger' : 'success'">{{ row.needsAttention ? "需关注" : "不关注" }}</el-tag></template></el-table-column>
        <el-table-column label="优先级" width="90"><template #default="{ row }">{{ priorityLabel(row.priority) }}</template></el-table-column>
        <el-table-column label="来源" width="110"><template #default="{ row }">{{ sourceLabel(row.source) }}</template></el-table-column>
        <el-table-column prop="matchedItem" label="命中项目" width="140" />
        <el-table-column prop="question" label="历史问题" min-width="220" show-overflow-tooltip />
        <el-table-column prop="reason" label="判断理由" min-width="220" />
        <el-table-column prop="summary" label="问题摘要" min-width="220" />
        <el-table-column label="详情" width="100"><template #default="{ row }"><el-popover placement="left" :width="560" trigger="click"><template #reference><el-button link type="primary">提示词/原始输出</el-button></template><div class="attention-preview-detail"><strong>最终提示词</strong><pre>{{ row.renderedPrompt || '关键词规则命中，未调用 AI' }}</pre><strong>模型原始输出</strong><pre>{{ row.rawOutput || '无' }}</pre></div></el-popover></template></el-table-column>
      </el-table>
    </article>
  </section>
</template>

<style scoped>
.attention-config-workspace { display: grid; gap: 18px; }
.attention-config-card { padding: 20px; border: 1px solid #e3e9e7; border-radius: 14px; background: #fff; }
.attention-config-card > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; margin-bottom: 18px; }
.attention-config-card h3 { margin: 0; color: #1f2d29; }
.attention-config-card p { margin: 6px 0 0; color: #73817c; font-size: 13px; }
.attention-switch-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.attention-switch-grid label { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px; border: 1px solid #e6ece9; border-radius: 10px; }
.attention-switch-grid span, .attention-prompt-editor > span { display: grid; gap: 5px; }
.attention-switch-grid small, .attention-term-grid small, .attention-prompt-editor small { color: #82908b; font-weight: 400; }
.attention-term-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-top: 16px; }
.attention-term-grid label { display: grid; gap: 7px; }
.attention-prompt-editor { display: grid; gap: 10px; margin-top: 18px; }
.recognition-item-editor { display: grid; gap: 10px; margin-top: 18px; }
.recognition-item-editor > header { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.recognition-item-editor > header span { display: grid; gap: 5px; }
.recognition-item-editor small { color: #82908b; font-weight: 400; }
.attention-preview-search { display: grid; grid-template-columns: minmax(260px, 520px) auto 1fr; align-items: center; gap: 10px; margin-bottom: 14px; }
.attention-preview-search span { color: #73817c; font-size: 13px; }
.attention-preview-detail { display: grid; gap: 8px; }
.attention-preview-detail pre { max-height: 300px; margin: 0 0 10px; padding: 10px; overflow: auto; border-radius: 8px; background: #f6f8f7; white-space: pre-wrap; word-break: break-word; }
@media (max-width: 980px) { .attention-switch-grid, .attention-term-grid { grid-template-columns: 1fr; } }
</style>
