(() => {
  const METRICS = [
    { id: "order_cost", label: "综合订单成本", labels: ["综合订单成本", "订单成本", "单均成本"] },
    { id: "refund_rate", label: "1小时内退款率", labels: ["1小时内退款率", "退款率"] },
    { id: "net_revenue", label: "净成交金额", labels: ["用户实际支付净成交金额", "净成交金额", "成交金额"] },
    { id: "orders", label: "净成交订单数", labels: ["净成交订单数", "整体成交订单数", "成交订单", "订单数"] },
    { id: "marketing_roi", label: "综合营销ROI", labels: ["综合营销ROI", "营销ROI", "ROI"] },
    { id: "net_roi", label: "净成交ROI", labels: ["净成交ROI", "支付ROI"] },
    { id: "spend", label: "整体消耗", labels: ["整体消耗", "综合成本", "消耗", "成本"] }
  ];
  const OPERATOR_LABELS = {
    lt: "低于",
    lte: "不高于",
    gt: "高于",
    gte: "不低于",
    increase_percent: "较上次上涨",
    decrease_percent: "较上次下降"
  };
  const DELIVERY_LABELS = {
    notify: "仅微信提醒",
    suggest: "提醒并生成建议",
    managed: "允许全托管调整"
  };

  function normalizeRule(raw = {}) {
    const metric = METRICS.find((item) => item.id === raw.metric);
    const operator = Object.hasOwn(OPERATOR_LABELS, raw.operator) ? raw.operator : "";
    const threshold = Number(raw.threshold);
    if (!metric || !operator || !Number.isFinite(threshold)) return null;
    return {
      id: Number(raw.id || 0),
      name: String(raw.name || `${metric.label}${OPERATOR_LABELS[operator]}${threshold}`).trim().slice(0, 120),
      metric: metric.id,
      operator,
      threshold,
      delivery: Object.hasOwn(DELIVERY_LABELS, raw.delivery) ? raw.delivery : "notify",
      cooldown_minutes: clamp(Number(raw.cooldown_minutes ?? raw.cooldownMinutes) || 30, 5, 1440),
      enabled: raw.enabled !== false,
      last_value: finiteOrNull(raw.last_value ?? raw.lastValue),
      last_evaluated_at: String(raw.last_evaluated_at || raw.lastEvaluatedAt || ""),
      last_triggered_at: String(raw.last_triggered_at || raw.lastTriggeredAt || "")
    };
  }

  function parseInstruction(value) {
    const text = compact(value);
    if (!text || !/(提醒|通知|盯盘|监控|关注|每当|如果|一旦|发微信|汇报|反馈)/.test(text)) return null;
    const metric = METRICS
      .flatMap((item) => item.labels.map((label) => ({ item, label })))
      .sort((left, right) => right.label.length - left.label.length)
      .find(({ label }) => text.toLowerCase().includes(label.toLowerCase()))?.item;
    if (!metric) return null;

    const conditions = [
      ["increase_percent", /(?:上涨|增加|上升|提升)\s*(?:达到|超过|高于)?\s*(-?\d+(?:\.\d+)?)\s*%/],
      ["decrease_percent", /(?:下降|减少|降低)\s*(?:达到|超过|高于)?\s*(-?\d+(?:\.\d+)?)\s*%/],
      ["lte", /(?:不高于|不超过|至多|小于等于|<=|≤)\s*(-?\d+(?:\.\d+)?)\s*%?/],
      ["gte", /(?:不低于|不少于|至少|大于等于|>=|≥)\s*(-?\d+(?:\.\d+)?)\s*%?/],
      ["lt", /(?:低于|小于|少于|不足|<)\s*(-?\d+(?:\.\d+)?)\s*%?/],
      ["gt", /(?:高于|大于|超过|多于|>)\s*(-?\d+(?:\.\d+)?)\s*%?/]
    ];
    const matched = conditions.map(([operator, pattern]) => ({ operator, match: text.match(pattern) })).find((item) => item.match);
    if (!matched) return null;
    const threshold = Math.abs(Number(matched.match[1]));
    if (!Number.isFinite(threshold)) return null;

    const cooldown = parseCooldown(text);
    const delivery = /(全托管|自动调整|自行调整|自动优化|自动执行)/.test(text)
      ? "managed"
      : /(建议|给出方案|让我确认|人工确认)/.test(text)
        ? "suggest"
        : "notify";
    const rule = normalizeRule({
      name: `${metric.label}${OPERATOR_LABELS[matched.operator]}${formatValue(metric.id, threshold, matched.operator)}`,
      metric: metric.id,
      operator: matched.operator,
      threshold,
      delivery,
      cooldown_minutes: cooldown,
      enabled: true
    });
    return rule ? { ...rule, source_text: text } : null;
  }

  function evaluateRule(rawRule, snapshot = {}, now = Date.now()) {
    const rule = normalizeRule(rawRule);
    if (!rule || !rule.enabled) return { evaluable: false, matched: false, reason: "规则未启用" };
    const currentValue = readMetricValue(snapshot, rule.metric);
    if (!Number.isFinite(currentValue)) return { evaluable: false, matched: false, reason: "当前页面没有该指标" };
    const previousValue = finiteOrNull(rule.last_value);
    const changePercent = Number.isFinite(previousValue) && previousValue !== 0
      ? ((currentValue - previousValue) / Math.abs(previousValue)) * 100
      : null;
    let matched = false;
    if (rule.operator === "lt") matched = currentValue < rule.threshold;
    if (rule.operator === "lte") matched = currentValue <= rule.threshold;
    if (rule.operator === "gt") matched = currentValue > rule.threshold;
    if (rule.operator === "gte") matched = currentValue >= rule.threshold;
    if (rule.operator === "increase_percent") matched = Number.isFinite(changePercent) && changePercent >= rule.threshold;
    if (rule.operator === "decrease_percent") matched = Number.isFinite(changePercent) && changePercent <= -rule.threshold;

    const lastTriggered = parseTimestamp(rule.last_triggered_at);
    const coolingDown = matched && lastTriggered > 0 && now - lastTriggered < rule.cooldown_minutes * 60 * 1000;
    return {
      evaluable: true,
      matched: matched && !coolingDown,
      conditionMatched: matched,
      coolingDown,
      currentValue,
      previousValue,
      changePercent,
      reason: coolingDown ? "处于通知冷却时间" : matched ? "达到规则条件" : "未达到规则条件"
    };
  }

  function readMetricValue(snapshot, metricId) {
    const metric = METRICS.find((item) => item.id === metricId);
    const rows = Array.isArray(snapshot?.summaryMetrics) ? snapshot.summaryMetrics : [];
    if (!metric) return null;
    for (const label of metric.labels) {
      const row = rows.find((item) => compact(item?.label) === label);
      const value = Number(row?.numericValue);
      if (Number.isFinite(value)) return value;
    }
    return null;
  }

  function describeRule(rawRule) {
    const rule = normalizeRule(rawRule);
    if (!rule) return "无效盯盘规则";
    const metric = METRICS.find((item) => item.id === rule.metric);
    return `${metric.label}${OPERATOR_LABELS[rule.operator]}${formatValue(rule.metric, rule.threshold, rule.operator)}；${DELIVERY_LABELS[rule.delivery]}；${rule.cooldown_minutes} 分钟内不重复`;
  }

  function formatTrigger(rawRule, evaluation) {
    const rule = normalizeRule(rawRule);
    const metric = METRICS.find((item) => item.id === rule?.metric);
    if (!rule || !metric) return "盯盘规则触发";
    const suffix = ["refund_rate"].includes(rule.metric) ? "%" : "";
    const lines = [`规则：${rule.name}`, `当前${metric.label}：${numberText(evaluation.currentValue)}${suffix}`];
    if (Number.isFinite(evaluation.changePercent)) lines.push(`较上次巡检：${evaluation.changePercent >= 0 ? "+" : ""}${numberText(evaluation.changePercent)}%`);
    lines.push(`条件：${OPERATOR_LABELS[rule.operator]}${formatValue(rule.metric, rule.threshold, rule.operator)}`);
    return lines.join("\n");
  }

  function parseCooldown(text) {
    const patterns = [
      /(?:冷却|间隔|每隔)\s*(\d+)\s*分钟/,
      /(\d+)\s*分钟内(?:不要|不再|避免)?重复/,
      /每\s*(\d+)\s*分钟(?:提醒|通知|汇报)/
    ];
    for (const pattern of patterns) {
      const value = Number(text.match(pattern)?.[1]);
      if (Number.isFinite(value)) return clamp(value, 5, 1440);
    }
    return 30;
  }

  function formatValue(metricId, value, operator) {
    return `${numberText(value)}${metricId === "refund_rate" || operator.includes("percent") ? "%" : ""}`;
  }

  function parseTimestamp(value) {
    const parsed = Date.parse(String(value || "").replace(" ", "T"));
    return Number.isFinite(parsed) ? parsed : 0;
  }

  function finiteOrNull(value) {
    if (value === null || value === undefined || value === "") return null;
    const number = Number(value);
    return Number.isFinite(number) ? number : null;
  }

  function numberText(value) {
    return Number(value).toLocaleString("zh-CN", { maximumFractionDigits: 2 });
  }

  function compact(value) {
    return String(value || "").replace(/\s+/g, " ").trim();
  }

  function clamp(value, minimum, maximum) {
    return Math.max(minimum, Math.min(maximum, value));
  }

  const api = {
    METRICS,
    OPERATOR_LABELS,
    DELIVERY_LABELS,
    normalizeRule,
    parseInstruction,
    evaluateRule,
    readMetricValue,
    describeRule,
    formatTrigger
  };
  if (typeof window !== "undefined") window.MMWQianchuanMonitorRules = api;
  if (typeof module !== "undefined" && module.exports) module.exports = api;
})();
