<!-- 规则新建 / 编辑页 -->
<template>
  <div class="rule-edit-page">
    <div class="page-header">
      <ElButton text :icon="ArrowLeft" @click="handleBack">返回</ElButton>
      <span class="page-title">{{ isEdit ? "编辑规则" : "新建规则" }}</span>
    </div>

    <!-- 左右布局：基础信息 + 提示词模板 -->
    <div class="edit-body">
      <!-- 基础信息 -->
      <ElCard class="form-card form-card--left" shadow="never">
        <template #header>
          <span class="section-title">基础信息</span>
        </template>
        <ElForm
          ref="formRef"
          :model="form"
          :rules="rules"
          label-width="110px"
          label-position="right"
        >
          <ElFormItem label="规则名称" prop="name" required>
            <ElInput
              v-model="form.name"
              placeholder="请输入规则名称"
              :maxlength="50"
              show-word-limit
            />
          </ElFormItem>

          <ElFormItem label="规则分类" prop="category_id" required>
            <ElTreeSelect
              v-model="form.category_id"
              :data="categoryTree"
              :props="treeSelectProps"
              node-key="id"
              check-strictly
              placeholder="请选择规则分类"
              filterable
              clearable
              style="width: 100%"
            />
          </ElFormItem>

          <ElFormItem label="规则描述" prop="description">
            <ElInput
              v-model="form.description"
              type="textarea"
              :rows="4"
              placeholder="请输入规则描述（可选）"
              :maxlength="200"
              show-word-limit
            />
          </ElFormItem>

          <ElFormItem label="状态" prop="status" required>
            <ElRadioGroup v-model="form.status">
              <ElRadio :value="0">启用</ElRadio>
              <ElRadio :value="1">停用</ElRadio>
            </ElRadioGroup>
          </ElFormItem>
        </ElForm>
      </ElCard>

      <!-- 提示词模板 -->
      <ElCard class="form-card form-card--right" shadow="never">
        <template #header>
          <span class="section-title">提示词模板</span>
        </template>
        <div class="prompt-section">
          <!-- 提示栏 -->
          <div class="prompt-hint-bar">
            <span class="hint-item">
              变量格式：<code class="var-code">${变量名}</code>，如
              <code class="var-code">${合同全文内容}</code>；
            </span>
            <span class="hint-item">
              知识库引用：<code class="kb-code">@知识库/文档名称</code>，如
              <code class="kb-code">@知识库/GB/T 50326-2018</code>
            </span>
          </div>

          <!-- 代码编辑器样式 textarea -->
          <div class="code-editor" ref="editorRef">
            <div class="line-numbers">
              <span
                v-for="n in lineCount"
                :key="n"
                class="line-num"
              >{{ n }}</span>
            </div>
            <textarea
              ref="textareaRef"
              v-model="form.prompt_template"
              class="code-textarea"
              spellcheck="false"
              placeholder="请输入提示词模板。输入 @ 可弹出知识库引用选择器"
              @input="handlePromptInput"
              @keydown="handlePromptKeydown"
              @scroll="syncScroll"
            />
          </div>

          <!-- 底部状态栏 -->
          <div class="editor-footer">
            <span class="tab-hint">按 Tab 键插入缩进</span>
            <span class="char-count">{{ form.prompt_template.length }} 字符</span>
          </div>
        </div>
      </ElCard>
    </div>

    <div class="footer-actions">
      <ElButton @click="handleBack">取消</ElButton>
      <ElButton type="primary" :loading="submitting" @click="handleSubmit">
        {{ isEdit ? "保存" : "创建" }}
      </ElButton>
    </div>

    <!-- 提示词模板 @ 引用弹窗 -->
    <PromptMentionDialog v-model="mentionVisible" @confirm="handleMentionConfirm" />
  </div>
</template>

<script setup lang="ts">
defineOptions({ name: "RuleEdit" });

import { ref, reactive, computed, nextTick, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage, type FormInstance, type FormRules } from "element-plus";
import { ArrowLeft } from "@element-plus/icons-vue";
import { RuleAPI } from "@/api/module_rule/rule";
import { useRuleCategory } from "../useRuleCategory";
import type { RuleForm } from "@/api/module_rule/rule";
import PromptMentionDialog from "./PromptMentionDialog.vue";

const route = useRoute();
const router = useRouter();
const { tree: categoryTree, loadTree } = useRuleCategory();

const treeSelectProps = {
  label: "name",
  children: "children",
};

const ruleId = computed(() => {
  const v = route.query.id;
  if (!v) return undefined;
  const n = Number(v);
  return Number.isFinite(n) ? n : undefined;
});
const isEdit = computed(() => ruleId.value != null);

const formRef = ref<FormInstance | null>(null);
const textareaRef = ref<HTMLTextAreaElement | null>(null);
const editorRef = ref<HTMLElement | null>(null);
const submitting = ref(false);

const form = reactive<RuleForm>({
  id: undefined,
  name: "",
  category_id: null,
  description: "",
  prompt_template: "",
  status: 0,
});

const rules: FormRules = {
  name: [
    { required: true, message: "请输入规则名称", trigger: "blur" },
    { max: 128, message: "最多 128 个字符", trigger: "blur" },
  ],
  category_id: [{ required: true, message: "请选择规则分类", trigger: "change" }],
  prompt_template: [
    { required: true, message: "请输入提示词模板", trigger: "blur" },
  ],
  status: [{ required: true, message: "请选择状态", trigger: "change" }],
};

// 行数统计（用于行号显示）
const lineCount = computed(() => {
  const text = form.prompt_template || "";
  return Math.max(text.split("\n").length, 1);
});

function syncScroll() {
  if (!textareaRef.value || !editorRef.value) return;
  const lineNums = editorRef.value.querySelector(".line-numbers") as HTMLElement | null;
  if (lineNums && textareaRef.value) {
    lineNums.scrollTop = textareaRef.value.scrollTop;
  }
}

// ============ 提示词模板 @ 引用 ============
const mentionVisible = ref(false);
let mentionStart: number = -1;

function handlePromptInput() {
  nextTick(() => {
    const el = textareaRef.value;
    if (!el) return;
    const caret = el.selectionStart;
    const value = form.prompt_template;
    if (value && caret > 0) {
      const ch = value[caret - 1];
      const prevCh = caret - 2 >= 0 ? value[caret - 2] : "";
      if (ch === "@" && prevCh !== "@") {
        mentionStart = caret - 1;
        mentionVisible.value = true;
      }
    }
    syncScroll();
  });
}

function handlePromptKeydown(e: Event | KeyboardEvent) {
  const ev = e as KeyboardEvent;
  // Tab 键插入缩进
  if (ev.key === "Tab" && !mentionVisible.value) {
    ev.preventDefault();
    const el = textareaRef.value;
    if (!el) return;
    const start = el.selectionStart;
    const end = el.selectionEnd;
    const value = form.prompt_template;
    form.prompt_template = value.slice(0, start) + "  " + value.slice(end);
    nextTick(() => {
      if (el) {
        el.focus();
        const pos = start + 2;
        el.setSelectionRange(pos, pos);
        syncScroll();
      }
    });
  }
}

function handleMentionConfirm(text: string) {
  if (mentionStart < 0) {
    form.prompt_template = `${form.prompt_template}${text}`;
    return;
  }
  const before = form.prompt_template.slice(0, mentionStart);
  const after = form.prompt_template.slice(mentionStart + 1);
  form.prompt_template = `${before}${text}${after}`;
  mentionStart = -1;
  nextTick(() => {
    const el = textareaRef.value;
    if (el) {
      const pos = before.length + text.length;
      el.focus();
      el.setSelectionRange(pos, pos);
      syncScroll();
    }
  });
}

// ============ 加载详情 ============
async function loadDetail() {
  if (!ruleId.value) return;
  try {
    const resp = await RuleAPI.detail(ruleId.value);
    const data = resp?.data?.data;
    if (data) {
      form.id = data.id;
      form.name = data.name ?? "";
      form.category_id = data.category_id ?? null;
      form.description = data.description ?? "";
      form.prompt_template = data.prompt_template ?? "";
      form.status = (data.status ?? 0) as 0 | 1;
    }
  } catch (e) {
    // 全局拦截器已处理
  }
}

// ============ 提交 ============
async function handleSubmit() {
  try {
    await formRef.value?.validate();
  } catch {
    return;
  }
  submitting.value = true;
  try {
    const payload: RuleForm = {
      id: form.id,
      name: form.name.trim(),
      category_id: form.category_id ?? null,
      description: form.description?.trim() || "",
      prompt_template: form.prompt_template,
      status: form.status,
    };
    if (isEdit.value && form.id) {
      await RuleAPI.update(form.id, payload);
      ElMessage.success("保存成功");
    } else {
      await RuleAPI.create(payload);
      ElMessage.success("创建成功");
    }
    router.push("/rule/list");
  } catch (e) {
  } finally {
    submitting.value = false;
  }
}

function handleBack() {
  router.push("/rule/list");
}

onMounted(async () => {
  await loadTree();
  if (isEdit.value) {
    await loadDetail();
  }
});
</script>

<style lang="scss" scoped>
.rule-edit-page {
  display: flex;
  flex-direction: column;
  height: 100%;
  // padding: 16px;
  gap: 12px;
  overflow: auto;
}

.page-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.page-title {
  font-size: 16px;
  font-weight: 600;
  color: #111827;
}

/* 左右布局主体 */
.edit-body {
  flex: 1;
  display: flex;
  gap: 12px;
  min-height: 0;
  align-items: flex-start;
  overflow: hidden;
}

.form-card {
  border-radius: 8px;
  border: 1px solid #e5e7eb;

  :deep(.el-card__header) {
    padding: 12px 20px;
    border-bottom: 1px solid #f3f4f6;
  }

  :deep(.el-card__body) {
    padding: 20px 24px 0px;
  }
}

.form-card--left {
  width: 420px;
  min-width: 420px;
  flex-shrink: 0;
}

.form-card--right {
  flex: 1;
  min-width: 0;
  height: 100%;
}

.section-title {
  font-size: 15px;
  font-weight: 600;
  color: #111827;
}

/* 提示词模板区域 */
.prompt-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  height: 100%;
}

.prompt-hint-bar {
  background: #f5f7fa;
  border: 1px solid #e5e7eb;
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  padding: 8px 14px;
  font-size: 12px;
  color: #6b7280;
  line-height: 1.8;
}

.hint-item + .hint-item {
  margin-left: 4px;
}

.var-code {
  color: #059669;
  background: #ecfdf5;
  padding: 1px 4px;
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
}

.kb-code {
  color: #2563eb;
  background: #eff6ff;
  padding: 1px 4px;
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
}

/* 代码编辑器样式 */
.code-editor {
  flex: 1;
  display: flex;
  border: 1px solid #dcdfe6;
  border-radius: 0 0 6px 6px;
  background: #fff;
  overflow: hidden;
  position: relative;

  &:focus-within {
    border-color: #409eff;
  }
}

.line-numbers {
  flex-shrink: 0;
  width: 40px;
  background: #fafafa;
  border-right: 1px solid #e5e7eb;
  padding: 8px 0;
  text-align: right;
  font-family: "SFMono-Regular", Consolas, monospace;
  font-size: 12px;
  color: #c0c4cc;
  line-height: 20px;
  overflow: hidden;
  user-select: none;
}

.line-num {
  display: block;
  padding-right: 8px;
}

.code-textarea {
  flex: 1;
  border: none;
  outline: none;
  resize: none;
  padding: 8px 12px;
  font-family: "SFMono-Regular", Consolas, "Courier New", monospace;
  font-size: 13px;
  line-height: 20px;
  color: #1f2937;
  background: #fff;
  min-height: 400px;
  tab-size: 2;
  white-space: pre;
  overflow-wrap: normal;
  overflow: auto;

  &::placeholder {
    color: #c0c4cc;
  }
}

.editor-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 2px;
  font-size: 12px;
  color: #9ca3af;
}

.footer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 4px;
}
</style>
