<template>
  <PageContainer title="通知策略中心">
    <QueryToolbar>
      <el-button v-if="canManage" type="primary" @click="openCreateDrawer">新增策略</el-button>
      <el-button v-if="canDispatch" type="warning" @click="openDispatchDialog">触发发送</el-button>
      <el-button v-if="canRead" @click="load">刷新</el-button>
    </QueryToolbar>

    <el-table :data="rows" class="mt-md" empty-text="暂无数据">
      <el-table-column prop="policyName" label="策略名称" width="160" />
      <el-table-column prop="eventCode" label="事件" width="150" :formatter="statusFormatter" />
      <el-table-column prop="channel" label="渠道" width="100" :formatter="statusFormatter" />
      <el-table-column prop="receiverType" label="对象" width="120" :formatter="statusFormatter" />
      <el-table-column prop="templateId" label="文案模板" min-width="160" :formatter="templateNameFormatter" />
      <el-table-column prop="status" label="状态" width="100" :formatter="statusFormatter" />
      <el-table-column label="操作" width="410">
        <template #default="{ row }">
          <el-button v-if="canManage" size="small" @click="openEdit(row)">编辑</el-button>
          <el-button v-if="canManage" size="small" @click="handleBindEvent(row)">绑定事件</el-button>
          <el-button v-if="canDispatch" size="small" type="primary" plain @click="openDispatchDialog(row)">触发本策略</el-button>
          <el-button v-if="canManage && row.status !== 'ENABLED'" size="small" type="success" @click="handleEnable(row.id)">启用</el-button>
          <el-button v-else-if="canManage" size="small" type="warning" @click="handleDisable(row.id)">停用</el-button>
          <el-button
            v-if="canManage && row.status === 'DISABLED'"
            size="small"
            type="danger"
            @click="handleDeletePolicy(row.id, row.policyName)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      class="mt-md"
      background
      layout="total, prev, pager, next, sizes"
      :total="policyTotal"
      v-model:current-page="policyPageNo"
      v-model:page-size="policyPageSize"
      :page-sizes="[10, 20, 50, 100]"
      @size-change="load"
      @current-change="load"
    />

    <SectionTitle>通知发送任务</SectionTitle>
    <el-table :data="taskRows" empty-text="暂无数据">
      <el-table-column prop="eventCode" label="事件" width="140" :formatter="statusFormatter" />
      <el-table-column prop="channel" label="渠道" width="100" :formatter="statusFormatter" />
      <el-table-column prop="receiverType" label="对象" width="110" :formatter="statusFormatter" />
      <el-table-column prop="receiverRef" label="接收标识" width="140" />
      <el-table-column prop="receiverResolveSource" label="接收人来源" width="130" :formatter="receiverResolveSourceFormatter" />
      <el-table-column prop="status" label="状态" width="100" :formatter="statusFormatter" />
      <el-table-column prop="retryCount" label="重试" width="80" />
      <el-table-column prop="providerMessageId" label="消息ID" width="180" />
      <el-table-column prop="receiptCode" label="回执码" width="100" />
      <el-table-column prop="receiptMessage" label="回执信息" width="140" />
      <el-table-column prop="errorMessage" label="错误信息" />
      <el-table-column prop="createdAt" label="创建时间" width="170" />
      <el-table-column prop="sentAt" label="发送时间" width="170" />
      <el-table-column prop="receiptAt" label="回执时间" width="170" />
      <el-table-column label="回执" width="100">
        <template #default="{ row }">
          <el-button v-if="canDispatch" size="small" :disabled="!row.providerMessageId" @click="handleMockReceipt(row)">回执成功</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="flex-end mt-md">
      <el-pagination
        :current-page="taskQuery.pageNo"
        :page-size="taskQuery.pageSize"
        :page-sizes="[10, 20, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="taskTotal"
        @current-change="handleTaskPageChange"
        @size-change="handleTaskPageSizeChange"
      />
    </div>

    <el-drawer v-model="createVisible" title="新增通知策略" :size="DRAWER_SIZE.md" destroy-on-close>
      <el-form ref="formRef" :model="form" label-position="left" :label-width="LABEL_WIDTH.md" :rules="formRules">
        <el-form-item label="策略名称" prop="policyName"><el-input v-model="form.policyName" /></el-form-item>
        <el-form-item label="事件" prop="eventCode">
          <el-select v-model="form.eventCode">
            <el-option label="审核通过" value="AUDIT_APPROVED" />
            <el-option label="审核拒绝" value="AUDIT_REJECTED" />
            <el-option label="财务已确认" value="FINANCE_CONFIRMED" />
            <el-option label="用户创建" value="USER_CREATED" />
          </el-select>
        </el-form-item>
        <el-form-item label="渠道" prop="channel">
          <el-select v-model="form.channel">
            <el-option label="站内" value="IN_APP" />
            <el-option label="短信" value="SMS" />
            <el-option label="邮件" value="EMAIL" />
          </el-select>
        </el-form-item>
        <el-form-item label="对象" prop="receiverType">
          <el-select v-model="form.receiverType">
            <el-option label="提交人" value="SUBMITTER" />
            <el-option label="审核人" value="AUDITOR" />
            <el-option label="财务角色" value="FINANCE_ROLE" />
            <el-option label="目标用户" value="TARGET_USER" />
          </el-select>
        </el-form-item>
        <el-form-item label="文案模板" prop="templateId">
          <el-select v-model="form.templateId" filterable placeholder="请选择模板" class="w-full">
            <el-option v-for="item in templateOptions" :key="item.id" :label="item.templateName" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="邮件主题"><el-input v-model="createComposer.subject" placeholder="例如：审核通知-${meetingTopic}" /></el-form-item>
        <el-form-item label="站内标题"><el-input v-model="createComposer.title" placeholder="例如：审核结果通知" /></el-form-item>
        <el-form-item label="正文模板">
          <el-input
            v-model="createComposer.content"
            type="textarea"
            :rows="3"
            placeholder="支持占位符，如：会议《${meetingTopic}》状态：${result}"
          />
        </el-form-item>
        <el-form-item label="变量键值">
          <div class="w-full">
            <el-space
              v-for="(item, idx) in createComposer.variables"
              :key="`create-var-${idx}`"
              class="flex mb-sm"
            >
              <el-input v-model="item.key" placeholder="变量名，如 meetingTopic" class="w-input-md" />
              <el-input v-model="item.value" placeholder="变量值，如 学术会议A" class="w-input-lg" />
              <el-button type="danger" plain @click="removeVariable(createComposer, idx)">删除</el-button>
            </el-space>
            <el-button plain @click="addVariable(createComposer)">新增变量</el-button>
          </div>
        </el-form-item>
        <el-form-item label="预览">
          <div class="preview-box">
            <div><b>主题：</b>{{ buildPreview(createComposer).subject || "-" }}</div>
            <div><b>标题：</b>{{ buildPreview(createComposer).title || "-" }}</div>
            <div><b>正文：</b>{{ buildPreview(createComposer).content || "-" }}</div>
          </div>
        </el-form-item>
        <el-form-item label="变量JSON">
          <el-input :model-value="buildVariablesJson(createComposer)" type="textarea" :rows="4" readonly />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="createVisible = false">取消</el-button>
        <el-button v-if="canManage" type="primary" @click="handleCreate">创建</el-button>
      </template>
    </el-drawer>

    <el-dialog v-model="editVisible" title="编辑通知策略" :width="DIALOG_WIDTH.md">
      <el-form ref="editFormRef" :model="editForm" label-position="left" :label-width="LABEL_WIDTH.md" :rules="formRules">
        <el-form-item label="策略名称" prop="policyName"><el-input v-model="editForm.policyName" /></el-form-item>
        <el-form-item label="事件" prop="eventCode">
          <el-select v-model="editForm.eventCode">
            <el-option label="审核通过" value="AUDIT_APPROVED" />
            <el-option label="审核拒绝" value="AUDIT_REJECTED" />
            <el-option label="财务已确认" value="FINANCE_CONFIRMED" />
            <el-option label="用户创建" value="USER_CREATED" />
          </el-select>
        </el-form-item>
        <el-form-item label="渠道" prop="channel">
          <el-select v-model="editForm.channel">
            <el-option label="站内" value="IN_APP" />
            <el-option label="短信" value="SMS" />
            <el-option label="邮件" value="EMAIL" />
          </el-select>
        </el-form-item>
        <el-form-item label="对象" prop="receiverType">
          <el-select v-model="editForm.receiverType">
            <el-option label="提交人" value="SUBMITTER" />
            <el-option label="审核人" value="AUDITOR" />
            <el-option label="财务角色" value="FINANCE_ROLE" />
            <el-option label="目标用户" value="TARGET_USER" />
          </el-select>
        </el-form-item>
        <el-form-item label="文案模板" prop="templateId">
          <el-select v-model="editForm.templateId" filterable placeholder="请选择模板" class="w-full">
            <el-option v-for="item in templateOptions" :key="item.id" :label="item.templateName" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="邮件主题"><el-input v-model="editComposer.subject" placeholder="例如：审核通知-${meetingTopic}" /></el-form-item>
        <el-form-item label="站内标题"><el-input v-model="editComposer.title" placeholder="例如：审核结果通知" /></el-form-item>
        <el-form-item label="正文模板">
          <el-input
            v-model="editComposer.content"
            type="textarea"
            :rows="3"
            placeholder="支持占位符，如：会议《${meetingTopic}》状态：${result}"
          />
        </el-form-item>
        <el-form-item label="变量键值">
          <div class="w-full">
            <el-space
              v-for="(item, idx) in editComposer.variables"
              :key="`edit-var-${idx}`"
              class="flex mb-sm"
            >
              <el-input v-model="item.key" placeholder="变量名，如 meetingTopic" class="w-input-md" />
              <el-input v-model="item.value" placeholder="变量值，如 学术会议A" class="w-input-lg" />
              <el-button type="danger" plain @click="removeVariable(editComposer, idx)">删除</el-button>
            </el-space>
            <el-button plain @click="addVariable(editComposer)">新增变量</el-button>
          </div>
        </el-form-item>
        <el-form-item label="预览">
          <div class="preview-box">
            <div><b>主题：</b>{{ buildPreview(editComposer).subject || "-" }}</div>
            <div><b>标题：</b>{{ buildPreview(editComposer).title || "-" }}</div>
            <div><b>正文：</b>{{ buildPreview(editComposer).content || "-" }}</div>
          </div>
        </el-form-item>
        <el-form-item label="变量JSON">
          <el-input :model-value="buildVariablesJson(editComposer)" type="textarea" :rows="4" readonly />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="editForm.status">
            <el-option label="启用" value="ENABLED" />
            <el-option label="停用" value="DISABLED" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSaveEdit">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="dispatchVisible" :title="dispatchDialogTitle" :width="DIALOG_WIDTH.md">
      <el-form ref="dispatchFormRef" :model="dispatchForm" label-position="left" :label-width="LABEL_WIDTH.lg" :rules="dispatchFormRules">
        <el-form-item label="事件" prop="eventCode">
          <el-select v-model="dispatchForm.eventCode" class="w-full">
            <el-option label="审核通过" value="AUDIT_APPROVED" />
            <el-option label="审核拒绝" value="AUDIT_REJECTED" />
            <el-option label="财务已确认" value="FINANCE_CONFIRMED" />
            <el-option label="用户创建" value="USER_CREATED" />
          </el-select>
        </el-form-item>
        <el-form-item label="业务类型">
          <el-input v-model="dispatchForm.bizType" placeholder="默认 MEETING" />
        </el-form-item>
        <el-form-item label="接收标识(可选)">
          <el-input v-model="dispatchForm.bizId" placeholder="可填 user-1 / 邮箱 / 手机号(显式覆盖)；不填按策略对象解析" />
          <div class="text-hint mt-xs">
            业务场景可填 meeting-2；用户创建场景可填 user-1；系统会按策略对象（提交人/审核人/财务角色/目标用户）解析接收人。
          </div>
        </el-form-item>
        <el-form-item label="变量键值">
          <div class="w-full">
            <el-space
              v-for="(item, idx) in dispatchComposer.variables"
              :key="`dispatch-var-${idx}`"
              class="flex mb-sm"
            >
              <el-input v-model="item.key" placeholder="变量名，如 meetingTopic" class="w-input-md" />
              <el-input v-model="item.value" placeholder="变量值，如 学术会议A" class="w-input-lg" />
              <el-button type="danger" plain @click="removeVariable(dispatchComposer, idx)">删除</el-button>
            </el-space>
            <el-space>
              <el-button plain @click="addVariable(dispatchComposer)">新增变量</el-button>
              <el-button plain @click="applyCurrentPolicyVariables">带入当前策略变量示例</el-button>
            </el-space>
          </div>
        </el-form-item>
        <el-form-item label="发送JSON">
          <el-input :model-value="buildDispatchVariablesJson()" type="textarea" :rows="5" readonly />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dispatchVisible = false">取消</el-button>
        <el-button type="primary" @click="handleDispatch">确认发送</el-button>
      </template>
    </el-dialog>
  </PageContainer>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import PageContainer from "../../components/PageContainer.vue";
import QueryToolbar from "../../components/QueryToolbar.vue";
import SectionTitle from "../../components/SectionTitle.vue";
import { DRAWER_SIZE, DIALOG_WIDTH, LABEL_WIDTH } from "../../constants/ui";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import {
  bindNotificationPolicyEvents,
  createNotificationPolicy,
  deleteNotificationPolicy,
  disableNotificationPolicy,
  dispatchNotification,
  enableNotificationPolicy,
  fetchNotificationPolicies,
  fetchNotificationTextTemplates,
  fetchNotificationTasks,
  ingestNotificationReceipt,
  updateNotificationPolicy,
} from "../../api/modules";
import { PERMS } from "../../constants/permissions";
import { useAuthStore } from "../../stores/auth";
import { toZhStatus } from "../../utils/status";

const authStore = useAuthStore();
const canRead = computed(() => authStore.hasPermission(PERMS.notification.policyRead));
const canManage = computed(() => authStore.hasPermission(PERMS.notification.policyManage));
const canDispatch = computed(() => authStore.hasPermission(PERMS.notification.dispatch));
const canTaskRead = computed(() => authStore.hasPermission(PERMS.notification.taskRead));
const rows = ref<any[]>([]);
const policyPageNo = ref(1);
const policyPageSize = ref(20);
const policyTotal = ref(0);
const taskRows = ref<any[]>([]);
const taskTotal = ref(0);
const taskQuery = ref<{ pageNo: number; pageSize: number }>({
  pageNo: 1,
  pageSize: 20,
});
const templateNameMap = ref<Record<number, string>>({});
const templateOptions = ref<Array<{ id: number; templateName: string }>>([]);
type VariableItem = { key: string; value: string };
type VariableComposer = { subject: string; title: string; content: string; variables: VariableItem[] };
const createVisible = ref(false);
const form = ref({
  policyName: "审核通过通知",
  eventCode: "AUDIT_APPROVED",
  channel: "IN_APP",
  receiverType: "SUBMITTER",
  templateId: 1,
  variablesJson: "{\"meetingTopic\":\"${meetingTopic}\"}",
  status: "ENABLED" as "ENABLED" | "DISABLED",
});
const createComposer = ref<VariableComposer>({
  subject: "",
  title: "审核通过通知",
  content: "会议《${meetingTopic}》已审核通过",
  variables: [{ key: "meetingTopic", value: "示例会议" }],
});

const editVisible = ref(false);
const editId = ref<number | null>(null);
const editForm = ref<any>({});
const editComposer = ref<VariableComposer>({
  subject: "",
  title: "",
  content: "",
  variables: [],
});
const formRef = ref<FormInstance>();
const editFormRef = ref<FormInstance>();
const dispatchFormRef = ref<FormInstance>();

const formRules = ref<FormRules>({
  policyName: [{ required: true, message: "请输入策略名称", trigger: "blur" }],
  eventCode: [{ required: true, message: "请选择事件", trigger: "change" }],
  channel: [{ required: true, message: "请选择渠道", trigger: "change" }],
  receiverType: [{ required: true, message: "请选择对象", trigger: "change" }],
  templateId: [{ required: true, message: "请选择文案模板", trigger: "change" }],
});

const dispatchFormRules = ref<FormRules>({
  eventCode: [{ required: true, message: "请选择事件", trigger: "change" }],
});
const statusFormatter = (_row: any, _column: any, value: unknown) => toZhStatus(value);
const isUserCreatedEvent = (value: unknown) => String(value || "").trim().toUpperCase() === "USER_CREATED";
const resolveReceiverTypeByEvent = (eventCode: unknown, currentReceiverType: unknown) => {
  if (isUserCreatedEvent(eventCode)) {
    return "TARGET_USER";
  }
  return String(currentReceiverType || "").trim().toUpperCase() === "TARGET_USER"
    ? "SUBMITTER"
    : String(currentReceiverType || "SUBMITTER");
};
const resolveBizTypeByEvent = (eventCode: unknown, currentBizType: unknown) => {
  if (isUserCreatedEvent(eventCode)) {
    return "USER";
  }
  return String(currentBizType || "").trim().toUpperCase() === "USER"
    ? "MEETING"
    : String(currentBizType || "MEETING");
};
const receiverResolveSourceFormatter = (_row: any, _column: any, value: unknown) => {
  const source = String(value || "").trim().toUpperCase();
  if (source === "EXPLICIT_INPUT") {
    return "显式输入";
  }
  if (source === "RECEIVER_TYPE_SUBMITTER") {
    return "提交人";
  }
  if (source === "RECEIVER_TYPE_AUDITOR") {
    return "审核人";
  }
  if (source === "RECEIVER_TYPE_FINANCE_ROLE") {
    return "财务角色";
  }
  if (source === "RECEIVER_TYPE_TARGET_USER") {
    return "目标用户";
  }
  if (source === "FALLBACK_CURRENT_USER") {
    return "当前用户兜底";
  }
  return source || "-";
};
const dispatchVisible = ref(false);
const dispatchDialogTitle = ref("触发通知发送");
const dispatchForm = ref({
  eventCode: "AUDIT_APPROVED",
  bizType: "MEETING",
  bizId: "",
  policyId: 0,
});
const dispatchComposer = ref<VariableComposer>({
  subject: "",
  title: "",
  content: "",
  variables: [],
});

const templateNameFormatter = (_row: any, _column: any, value: unknown) => {
  const templateId = Number(value || 0);
  if (!templateId) {
    return "-";
  }
  return templateNameMap.value[templateId] || `模板#${templateId}`;
};

const loadTemplateMap = async () => {
  try {
    const resp = await fetchNotificationTextTemplates();
    const list = resp?.data?.list || [];
    const map: Record<number, string> = {};
    const options: Array<{ id: number; templateName: string }> = [];
    list.forEach((item: any) => {
      const id = Number(item?.id || 0);
      if (id > 0) {
        const name = item?.templateName || `文案模板#${id}`;
        map[id] = name;
        options.push({ id, templateName: name });
      }
    });
    templateNameMap.value = map;
    templateOptions.value = options;
    if (options.length > 0) {
      if (!options.some((x) => x.id === Number(form.value.templateId || 0))) {
        form.value.templateId = options[0].id;
      }
      if (editForm.value && editForm.value.templateId != null) {
        const currentEditId = Number(editForm.value.templateId || 0);
        if (!options.some((x) => x.id === currentEditId)) {
          editForm.value.templateId = options[0].id;
        }
      }
    }
  } catch (_e) {
    templateNameMap.value = {};
    templateOptions.value = [];
  }
};

const openCreateDrawer = () => {
  form.value = {
    policyName: "审核通过通知",
    eventCode: "AUDIT_APPROVED",
    channel: "IN_APP",
    receiverType: "SUBMITTER",
    templateId: 1,
    variablesJson: "{\"meetingTopic\":\"${meetingTopic}\"}",
    status: "ENABLED",
  };
  createComposer.value = parseVariablesJson(form.value.variablesJson);
  createVisible.value = true;
};

watch(
  () => form.value.eventCode,
  (eventCode) => {
    form.value.receiverType = resolveReceiverTypeByEvent(eventCode, form.value.receiverType);
  }
);

watch(
  () => editForm.value?.eventCode,
  (eventCode) => {
    if (!editForm.value) {
      return;
    }
    editForm.value.receiverType = resolveReceiverTypeByEvent(eventCode, editForm.value.receiverType);
  }
);

watch(
  () => dispatchForm.value.eventCode,
  (eventCode) => {
    dispatchForm.value.bizType = resolveBizTypeByEvent(eventCode, dispatchForm.value.bizType);
  }
);

const load = async () => {
  if (!canRead.value) {
    rows.value = [];
    taskRows.value = [];
    taskTotal.value = 0;
    return;
  }
  const resp = await fetchNotificationPolicies({ pageNo: policyPageNo.value, pageSize: policyPageSize.value });
  rows.value = resp?.data?.list || [];
  policyTotal.value = Number(resp?.data?.total || 0);
  if (canTaskRead.value) {
    const taskResp = await fetchNotificationTasks(taskQuery.value);
    taskRows.value = taskResp?.data?.list || [];
    taskTotal.value = Number(taskResp?.data?.total || 0);
    taskQuery.value.pageNo = Number(taskResp?.data?.pageNo || taskQuery.value.pageNo || 1);
    taskQuery.value.pageSize = Number(taskResp?.data?.pageSize || taskQuery.value.pageSize || 20);
  } else {
    taskRows.value = [];
    taskTotal.value = 0;
  }
};

const handleTaskPageChange = async (pageNo: number) => {
  taskQuery.value.pageNo = Number(pageNo || 1);
  await load();
};

const handleTaskPageSizeChange = async (pageSize: number) => {
  taskQuery.value.pageSize = Number(pageSize || 20);
  taskQuery.value.pageNo = 1;
  await load();
};

const handleCreate = async () => {
  if (!formRef.value) return;
  const valid = await formRef.value.validate().catch(() => false);
  if (!valid) return;

  if (templateOptions.value.length === 0) {
    ElMessage.warning("请先创建通知文案模板");
    return;
  }
  await createNotificationPolicy({
    ...form.value,
    variablesJson: buildVariablesJson(createComposer.value),
  });
  ElMessage.success("通知策略创建成功");
  createVisible.value = false;
  await load();
};

const openDispatchDialog = (row?: any) => {
  const sourcePolicy = row || null;
  let sourceComposer: VariableComposer = createComposer.value;
  if (sourcePolicy && sourcePolicy.variablesJson) {
    sourceComposer = parseVariablesJson(String(sourcePolicy.variablesJson || ""));
  }
  dispatchForm.value = {
    eventCode: sourcePolicy?.eventCode || form.value.eventCode || "AUDIT_APPROVED",
    bizType: resolveBizTypeByEvent(sourcePolicy?.eventCode || form.value.eventCode, sourcePolicy?.bizType),
    bizId: "",
    policyId: sourcePolicy?.id ? Number(sourcePolicy.id) : 0,
  };
  dispatchDialogTitle.value = sourcePolicy?.policyName
    ? `触发通知发送 - ${String(sourcePolicy.policyName)}`
    : "触发通知发送";
  dispatchComposer.value = {
    subject: "",
    title: "",
    content: "",
    variables: sourceComposer.variables.map((x) => ({ key: x.key, value: x.value })),
  };
  dispatchVisible.value = true;
};

const handleDispatch = async () => {
  if (!dispatchFormRef.value) return;
  const valid = await dispatchFormRef.value.validate().catch(() => false);
  if (!valid) return;

  const variablesJson = buildDispatchVariablesJson();
  await dispatchNotification({
    idempotencyKey: `dispatch-${Date.now()}`,
    eventCode: dispatchForm.value.eventCode,
    bizType: dispatchForm.value.bizType || "MEETING",
    bizId: dispatchForm.value.bizId ? dispatchForm.value.bizId : undefined,
    variablesJson,
    policyId: dispatchForm.value.policyId > 0 ? dispatchForm.value.policyId : undefined,
  });
  ElMessage.success(dispatchForm.value.policyId ? "当前策略通知任务已触发" : "通知任务已触发");
  dispatchVisible.value = false;
  await load();
};

const handleMockReceipt = async (row: any) => {
  await ingestNotificationReceipt({
    taskId: row.id,
    providerMessageId: row.providerMessageId,
    receiptCode: "DELIVERED",
    receiptMessage: "供应商回执送达",
    delivered: true,
  });
  ElMessage.success("回执已写入");
  await load();
};

const openEdit = (row: any) => {
  editId.value = row.id;
  editForm.value = {
    policyName: row.policyName,
    eventCode: row.eventCode,
    channel: row.channel,
    receiverType: row.receiverType,
    templateId: row.templateId,
    variablesJson: row.variablesJson,
    status: row.status,
  };
  editComposer.value = parseVariablesJson(row.variablesJson);
  editVisible.value = true;
};

const handleSaveEdit = async () => {
  if (!editId.value) return;

  if (!editFormRef.value) return;
  const valid = await editFormRef.value.validate().catch(() => false);
  if (!valid) return;

  if (templateOptions.value.length === 0) {
    ElMessage.warning("请先创建通知文案模板");
    return;
  }
  await updateNotificationPolicy(editId.value, {
    ...editForm.value,
    variablesJson: buildVariablesJson(editComposer.value),
  });
  ElMessage.success("通知策略更新成功");
  editVisible.value = false;
  await load();
};

const handleBindEvent = async (row: any) => {
  await bindNotificationPolicyEvents(row.id, { eventCode: row.eventCode });
  ElMessage.success("事件绑定成功");
  await load();
};

const handleEnable = async (id: number) => {
  await enableNotificationPolicy(id);
  ElMessage.success("策略已启用");
  await load();
};

const handleDisable = async (id: number) => {
  await disableNotificationPolicy(id);
  ElMessage.success("策略已停用");
  await load();
};

const handleDeletePolicy = async (id: number, name: string) => {
  await ElMessageBox.confirm(`确认删除通知策略「${name}」？删除后不可恢复。`, "删除策略", {
    type: "warning",
    confirmButtonText: "确认删除",
    cancelButtonText: "取消",
  });
  await deleteNotificationPolicy(id);
  ElMessage.success("通知策略已删除");
  await load();
};

const addVariable = (composer: VariableComposer) => {
  composer.variables.push({ key: "", value: "" });
};

const removeVariable = (composer: VariableComposer, index: number) => {
  composer.variables.splice(index, 1);
};

const parseVariablesJson = (raw?: string): VariableComposer => {
  const fallback: VariableComposer = { subject: "", title: "", content: "", variables: [] };
  if (!raw || !raw.trim()) {
    return fallback;
  }
  try {
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
      return fallback;
    }
    const data = parsed as Record<string, unknown>;
    const composer: VariableComposer = {
      subject: String(data.subject || ""),
      title: String(data.title || ""),
      content: String(data.content || data.message || ""),
      variables: [],
    };
    Object.entries(data).forEach(([key, value]) => {
      if (["subject", "title", "content", "message"].includes(key)) {
        return;
      }
      composer.variables.push({ key, value: value == null ? "" : String(value) });
    });
    return composer;
  } catch (_e) {
    return fallback;
  }
};

const buildVariablesJson = (composer: VariableComposer): string => {
  const result: Record<string, string> = {};
  if (composer.subject.trim()) {
    result.subject = composer.subject.trim();
  }
  if (composer.title.trim()) {
    result.title = composer.title.trim();
  }
  if (composer.content.trim()) {
    result.content = composer.content.trim();
  }
  composer.variables.forEach((item) => {
    const key = item.key.trim();
    if (!key) {
      return;
    }
    result[key] = item.value;
  });
  return JSON.stringify(result);
};

const buildDispatchVariablesJson = (): string => {
  const result: Record<string, string> = {};
  dispatchComposer.value.variables.forEach((item) => {
    const key = item.key.trim();
    if (!key) {
      return;
    }
    result[key] = item.value;
  });
  return JSON.stringify(result);
};

const applyCurrentPolicyVariables = () => {
  dispatchComposer.value.variables = createComposer.value.variables.map((x) => ({ key: x.key, value: x.value }));
};

const renderTemplate = (template: string, vars: Record<string, string>): string => {
  if (!template) {
    return "";
  }
  return template.replace(/\$\{([^}]+)\}/g, (_m, key: string) => {
    const k = String(key || "").trim();
    return vars[k] ?? "";
  });
};

const buildPreview = (composer: VariableComposer): { subject: string; title: string; content: string } => {
  const vars: Record<string, string> = {};
  composer.variables.forEach((item) => {
    const key = item.key.trim();
    if (!key) {
      return;
    }
    vars[key] = item.value;
  });
  const subjectTpl = composer.subject.trim() || composer.title.trim();
  const titleTpl = composer.title.trim() || composer.subject.trim();
  const contentTpl = composer.content.trim();
  return {
    subject: renderTemplate(subjectTpl, vars),
    title: renderTemplate(titleTpl, vars),
    content: renderTemplate(contentTpl, vars),
  };
};

onMounted(async () => {
  await Promise.all([loadTemplateMap(), load()]);
});
</script>
