(() => {
  const MODE_LABELS = {
    overall: ["全域投放"],
    multiplier: ["乘方", "千川乘方"],
    standard: ["标准投放"]
  };
  const TARGET_LABELS = {
    product: ["推商品", "商品"],
    live_room: ["推直播间", "直播"]
  };
  const SCENES = {
    overall_product: { scope: "overall_promotion", label: "全域 · 推商品" },
    overall_live_room: { scope: "live_room", label: "全域 · 推直播间" },
    multiplier_product: { scope: "multiplier_product", label: "乘方 · 推商品" },
    multiplier_live_room: { scope: "multiplier_live_room", label: "乘方 · 推直播间" }
  };
  const ACCOUNT_QUERY_KEYS = ["aavid", "aadvid", "advertiser_id", "account_id", "accountId", "ad_id"];
  const SUMMARY_METRIC_LABELS = [
    "用户实际支付净成交金额",
    "净成交金额转化率",
    "整体成交订单数",
    "整体成交金额",
    "综合营销ROI",
    "综合订单成本",
    "1小时内退款率",
    "净成交订单数",
    "净成交金额",
    "净成交ROI",
    "整体消耗",
    "综合成本",
    "预估达人佣金"
  ];
  const PLAN_METADATA_LABELS = new Set(["", "计划", "计划状态", "投放状态", "投放设置", "营销服务", "调控工具", "操作", "投放类型"]);
  const TABLE_SELECTOR = "table,[role='table'],[role='grid']";
  const ROW_SELECTOR = "tr,[role='row']";
  const CELL_SELECTOR = "th,td,[role='columnheader'],[role='cell'],[role='gridcell']";
  const DATA_RANGE_LABELS = ["全域期间数据", "乘方期间数据"];
  const PLAN_TAB_LABELS = ["商品自选", "全店托管"];

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

  function classifySignals(signals = {}) {
    const selected = new Set((signals.selectedLabels || []).map(compactText).filter(Boolean));
    const deliveryMode = findSignalKey(MODE_LABELS, selected);
    const promotionTarget = findSignalKey(TARGET_LABELS, selected);
    const scene = SCENES[`${deliveryMode}_${promotionTarget}`];
    if (scene) return { deliveryMode, promotionTarget, supported: true, ...scene };
    if (deliveryMode === "standard") {
      return {
        deliveryMode,
        promotionTarget,
        supported: false,
        scope: "",
        label: promotionTarget === "unknown" ? "标准投放" : `标准投放 · ${TARGET_LABELS[promotionTarget][0]}`,
        message: "已识别到标准投放；当前 Agent 仅支持全域投放和乘方。"
      };
    }
    return {
      deliveryMode,
      promotionTarget,
      supported: false,
      scope: "",
      label: "场景未识别",
      message: "请进入全域投放的“推商品 / 推直播间”，或乘方的“商品 / 直播”页面。"
    };
  }

  function findSignalKey(dictionary, selected) {
    return Object.entries(dictionary).find(([, aliases]) => aliases.some((label) => selected.has(label)))?.[0] || "unknown";
  }

  function detectPageContext(doc = document, currentLocation = location) {
    const selectedLabels = [
      findSelectedLabel(doc, Object.values(MODE_LABELS).flat(), currentLocation),
      findSelectedLabel(doc, Object.values(TARGET_LABELS).flat(), currentLocation)
    ].filter(Boolean);
    const visual = classifySignals({ selectedLabels });
    return visual.supported ? visual : classifyLocation(currentLocation) || visual;
  }

  function classifyLocation(currentLocation) {
    try {
      const url = new URL(currentLocation.href);
      const normalizedPath = url.pathname.replace(/\/+$/, "");
      const deliveryMode = normalizedPath === "/uni-prom/overall"
        ? "multiplier"
        : normalizedPath === "/uni-prom" ? "overall" : "unknown";
      const umg = readLocationParam(url, "umg");
      const promotionTarget = umg === "1" ? "product" : umg === "2" ? "live_room" : "unknown";
      const scene = SCENES[`${deliveryMode}_${promotionTarget}`];
      return scene ? { deliveryMode, promotionTarget, supported: true, ...scene } : null;
    } catch {
      return null;
    }
  }

  function readLocationParam(url, key) {
    const direct = url.searchParams.get(key);
    if (direct) return direct;
    const match = String(url.hash || "").match(new RegExp(`(?:^|[&#?])${escapeRegExp(key)}=([^&]*)`, "i"));
    return match ? decodeURIComponent(match[1]) : "";
  }

  function findSelectedLabel(doc, labels, currentLocation) {
    const wanted = new Set(labels);
    const scores = new Map(labels.map((label) => [label, -1]));
    const nodes = Array.from(doc.querySelectorAll("a,button,[role='tab'],[aria-selected],[aria-current],li,span,div"));
    for (const node of nodes) {
      if (node.closest?.("#mmw-qianchuan-agent-root")) continue;
      const label = compactText(node.innerText || node.textContent);
      if (!wanted.has(label) || !isVisible(node)) continue;
      scores.set(label, Math.max(scores.get(label), selectionScore(node, label, currentLocation)));
    }
    const ranked = Array.from(scores.entries()).sort((left, right) => right[1] - left[1]);
    const [bestLabel, bestScore] = ranked[0] || ["", -1];
    const nextScore = ranked[1]?.[1] ?? -1;
    if (bestScore >= 40 || (bestScore >= 8 && bestScore - nextScore >= 4)) return bestLabel;
    return "";
  }

  function selectionScore(node, label, currentLocation) {
    let score = 0;
    let current = node;
    for (let depth = 0; current && depth < 4; depth += 1, current = current.parentElement) {
      if (compactText(current.innerText || current.textContent) !== label) break;
      const ariaSelected = current.getAttribute?.("aria-selected");
      const ariaCurrent = current.getAttribute?.("aria-current");
      if (ariaSelected === "true" || (ariaCurrent && ariaCurrent !== "false")) score = Math.max(score, 100);
      if (["active", "selected", "checked", "current"].includes(String(current.dataset?.state || "").toLowerCase())) score = Math.max(score, 90);
      if (String(current.dataset?.active || "").toLowerCase() === "true") score = Math.max(score, 90);
      if (String(current.dataset?.selected || "").toLowerCase() === "true") score = Math.max(score, 90);
      if (/(^|[-_\s])(active|selected|checked|current)([-_\s]|$)/i.test(String(current.className || ""))) score = Math.max(score, 80);
      if (current.matches?.("a[href]") && linkMatchesLocation(current, currentLocation)) score = Math.max(score, 45);
      score += visualSelectionScore(current);
    }
    return score;
  }

  function visualSelectionScore(node) {
    const view = node.ownerDocument?.defaultView;
    if (!view?.getComputedStyle) return 0;
    const style = view.getComputedStyle(node);
    let score = 0;
    const color = parseRgb(style.color);
    if (color && color.b - Math.max(color.r, color.g) >= 35) score += 10;
    if (Number.parseInt(style.fontWeight, 10) >= 600) score += 2;
    if (Number.parseFloat(style.borderBottomWidth) > 1 && style.borderBottomStyle !== "none") score += 8;
    return score;
  }

  function parseRgb(value) {
    const match = String(value || "").match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/i);
    return match ? { r: Number(match[1]), g: Number(match[2]), b: Number(match[3]) } : null;
  }

  function linkMatchesLocation(node, currentLocation) {
    try {
      const target = new URL(node.href, currentLocation.href);
      return target.origin === currentLocation.origin
        && target.pathname === currentLocation.pathname
        && (!target.search || target.search === currentLocation.search);
    } catch {
      return false;
    }
  }

  function isVisible(node) {
    const view = node.ownerDocument?.defaultView;
    if (!view?.getComputedStyle) return true;
    const style = view.getComputedStyle(node);
    const rect = node.getBoundingClientRect?.() || { width: 1, height: 1 };
    return style.display !== "none" && style.visibility !== "hidden" && rect.width > 0 && rect.height > 0;
  }

  function extractAccountKey(signals = {}) {
    try {
      const url = new URL(signals.url || "https://qianchuan.jinritemai.com/");
      for (const key of ACCOUNT_QUERY_KEYS) {
        const value = cleanAccountKey(url.searchParams.get(key));
        if (value) return value;
      }
      const hashQuery = String(url.hash || "").replace(/^#(?:[^?]*\?)?/, "");
      for (const key of ACCOUNT_QUERY_KEYS) {
        const match = hashQuery.match(new RegExp(`(?:^|&)${escapeRegExp(key)}=([^&]+)`, "i"));
        const value = cleanAccountKey(match ? decodeURIComponent(match[1]) : "");
        if (value) return value;
      }
    } catch {}
    for (const value of signals.attributeValues || []) {
      const cleaned = cleanAccountKey(value);
      if (cleaned) return cleaned;
    }
    for (const text of signals.textCandidates || []) {
      const compact = compactText(text);
      const labelled = compact.match(/(?:千川账户|广告账户|账户ID|账号ID)\s*[:：]?\s*([A-Za-z0-9_.:@-]{3,128})/i);
      if (labelled) return cleanAccountKey(labelled[1]);
      const headerId = compact.match(/^ID\s*[:：]\s*([A-Za-z0-9_.:@-]{8,128})$/i);
      if (headerId) return cleanAccountKey(headerId[1]);
    }
    return "";
  }

  function detectAccountKey(doc = document, currentLocation = location) {
    const attributeValues = [];
    for (const node of doc.querySelectorAll("[data-advertiser-id],[data-account-id],[data-aavid],[data-aadvid]")) {
      attributeValues.push(
        node.getAttribute("data-advertiser-id"),
        node.getAttribute("data-account-id"),
        node.getAttribute("data-aavid"),
        node.getAttribute("data-aadvid")
      );
    }
    const textCandidates = collectAccountTextCandidates(doc);
    return extractAccountKey({ url: currentLocation.href, attributeValues, textCandidates });
  }

  function detectAccountName(doc = document, accountKey = "") {
    return extractAccountName({ accountKey, textCandidates: collectAccountTextCandidates(doc) });
  }

  function collectAccountTextCandidates(doc) {
    const textCandidates = [];
    for (const node of doc.querySelectorAll("header,header *,nav,nav *,[class*='header'],[class*='header'] *,[class*='account'],[class*='account'] *")) {
      if (!isVisible(node)) continue;
      const rect = node.getBoundingClientRect?.();
      const text = compactText(node.innerText || node.textContent);
      if ((!rect || rect.top < 240) && text.length <= 160) textCandidates.push(text);
    }
    textCandidates.push((doc.body?.innerText || "").slice(0, 8000));
    return textCandidates;
  }

  function extractAccountName(signals = {}) {
    const accountKey = cleanAccountKey(signals.accountKey);
    const candidates = (signals.textCandidates || []).map(compactText).filter(Boolean).sort((a, b) => a.length - b.length);
    for (const text of candidates) {
      let value = "";
      if (accountKey && text.includes(accountKey)) value = text.slice(0, text.indexOf(accountKey));
      if (!value) {
        const labelled = text.match(/(?:千川账户|广告账户|账户名称|账号名称)\s*[:：]?\s*([^|｜]{2,80}?)(?=\s+(?:ID|账户ID|账号ID)\s*[:：]|$)/i);
        value = labelled?.[1] || "";
      }
      value = compactText(value)
        .replace(/(?:账户ID|账号ID|ID)\s*[:：]?\s*$/i, "")
        .replace(/^(?:千川账户|广告账户|账户名称|账号名称)\s*[:：]?\s*/i, "")
        .split(/[|｜]/).pop().trim();
      if (value.length >= 2 && value.length <= 80 && /[\p{L}\p{Script=Han}]/u.test(value)
        && !/^(?:首页|千川|全域投放|标准投放|乘方|广告账户|千川账户)$/i.test(value)) return value;
    }
    return "";
  }

  function extractPageData(signals = {}) {
    const lines = [signals.text, ...(signals.controlTexts || [])]
      .join("\n")
      .split(/\r?\n/)
      .map(compactText)
      .filter(Boolean);
    const summaryMetrics = Array.isArray(signals.summaryMetrics)
      ? signals.summaryMetrics.slice(0, SUMMARY_METRIC_LABELS.length).map(normalizeMetricRecord).filter(Boolean)
      : SUMMARY_METRIC_LABELS.map((label) => extractMetric(lines, label)).filter(Boolean);
    const joined = lines.join("\n");
    const planCountMatch = joined.match(/共\s*(\d+)\s*条计划/);
    const pageUpdatedText = compactText(signals.pageUpdatedText)
      || joined.match(/\b\d{2}-\d{2}\s+\d{2}:\d{2}\s*更新/)?.[0]
      || "";
    const emptyReason = lines.find((line) => /已删除全店计划|当前无在投的全店托管|暂无数据|没有符合.*计划|未找到.*计划/.test(line)) || "";
    return {
      summaryMetrics,
      dataRange: DATA_RANGE_LABELS.find((label) => lines.includes(label)) || "",
      planTab: compactText(signals.selectedPlanTab) || "",
      planCount: planCountMatch ? Number(planCountMatch[1]) : null,
      emptyReason: emptyReason.slice(0, 240),
      planTotals: Array.isArray(signals.planTotals) ? signals.planTotals.slice(0, 24).map(normalizeMetricRecord).filter(Boolean) : [],
      pageUpdatedText
    };
  }

  function detectPageData(doc = document, currentLocation = location) {
    const selectedPlanTab = findSelectedLabel(doc, PLAN_TAB_LABELS, currentLocation);
    const controlTexts = Array.from(doc.querySelectorAll("input,[role='combobox'],[aria-haspopup='listbox']"))
      .flatMap((node) => [node.value, node.getAttribute?.("aria-label"), node.innerText || node.textContent])
      .map(compactText)
      .filter((text) => DATA_RANGE_LABELS.includes(text));
    return extractPageData({
      text: doc.body?.innerText || "",
      controlTexts,
      selectedPlanTab,
      summaryMetrics: extractSummaryMetrics(doc),
      planTotals: extractPlanTotals(doc),
      pageUpdatedText: extractPageUpdatedText(doc)
    });
  }

  function extractSummaryMetrics(doc = document) {
    const nodes = Array.from(doc.querySelectorAll("div,span,p,strong,label,section,li"));
    const records = [];
    for (const label of SUMMARY_METRIC_LABELS) {
      const labelNodes = nodes.filter((node) => compactText(node.innerText || node.textContent) === label
        && isVisible(node)
        && !node.closest?.(`${TABLE_SELECTOR},${ROW_SELECTOR},[role='columnheader'],[role='cell'],[role='gridcell']`));
      const record = labelNodes.map((node) => metricFromSummaryNode(node, label)).find(Boolean);
      if (record) records.push(record);
    }
    return records;
  }

  function metricFromSummaryNode(node, label) {
    let current = node;
    for (let depth = 0; current && depth < 5; depth += 1, current = current.parentElement) {
      if (current.matches?.(`${TABLE_SELECTOR},${ROW_SELECTOR},[role='columnheader'],[role='cell'],[role='gridcell']`)) return null;
      const text = compactText(current.innerText || current.textContent);
      if (!text.startsWith(label) || text.length > 240) continue;
      const record = extractMetric([text], label);
      if (record) return record;
    }
    return null;
  }

  function extractPlanTotals(doc = document) {
    for (const table of tableElements(doc)) {
      const headers = tableHeaders(table);
      if (!headers.includes("计划")) continue;
      const totalRow = tableRows(table).find((row) => /^共\s*\d+\s*条计划/.test(compactText(row.innerText || row.textContent)));
      if (!totalRow) continue;
      const records = metricCells(headers, rowCells(totalRow).map(cellText));
      if (records.length) return records;
    }
    return [];
  }

  function extractPlanRows(doc = document) {
    const tables = tableElements(doc);
    for (const table of tables) {
      const headers = tableHeaders(table);
      if (!headers.includes("计划")) continue;
      const directRows = planRowsFromTable(table, headers);
      if (directRows.length) return directRows;
      for (const relatedTable of relatedTableElements(table, tables)) {
        const relatedRows = planRowsFromTable(relatedTable, headers);
        if (relatedRows.length) return relatedRows;
      }
    }
    return [];
  }

  function planRowsFromTable(table, headers) {
    return tableRows(table)
      .map((row) => rowCells(row).map(cellText))
      .filter((values) => values.length === headers.length)
      .map((values) => buildPlanRow(headers, values))
      .filter(Boolean)
      .slice(0, 40);
  }

  function relatedTableElements(table, tables) {
    let container = table.parentElement;
    for (let depth = 0; container && depth < 3; depth += 1, container = container.parentElement) {
      const related = tables.filter((candidate) => candidate !== table && container.contains?.(candidate));
      if (related.length) return related;
    }
    return [];
  }

  function buildPlanRow(headersValue, valuesValue) {
    const headers = (Array.isArray(headersValue) ? headersValue : []).map(normalizeColumnLabel);
    const values = (Array.isArray(valuesValue) ? valuesValue : []).map(compactText);
    const pairs = headers.map((label, index) => ({ label, rawValue: values[index] || "" }));
    const text = pairs.filter((item) => item.label && item.rawValue)
      .map((item) => `${item.label} ${item.rawValue}`).join(" ").slice(0, 2400);
    const id = text.match(/(?:计划)?ID\s*[：:]\s*(\d{10,24})/i)?.[1]
      || values.join(" ").match(/\b(\d{10,24})\b/)?.[1]
      || "";
    if (!id) return null;
    const planCell = pairs.find((item) => item.label === "计划")?.rawValue || values.join(" ");
    const statusText = pairs.find((item) => item.label === "计划状态" || item.label === "投放状态")?.rawValue || text;
    return {
      id,
      name: extractPlanName(planCell, id),
      text,
      metrics: metricCells(headers, values),
      status: /(?:已暂停|暂停中|已关闭)/.test(statusText) ? "paused" : /(?:投放中|生效中|已开启)/.test(statusText) ? "active" : "",
      budget: metricFromPairs(pairs, ["日预算", "预算"]),
      roi: metricFromPairs(pairs, ["净成交ROI目标", "综合营销ROI目标", "目标ROI", "ROI目标"])
    };
  }

  function tableElements(doc) {
    return Array.from(doc.querySelectorAll(TABLE_SELECTOR)).filter(isVisible);
  }

  function tableRows(table) {
    return Array.from(table.querySelectorAll(ROW_SELECTOR))
      .filter((row) => isVisible(row) && row.closest?.(TABLE_SELECTOR) === table);
  }

  function tableHeaders(table) {
    const headerRow = tableRows(table).find((row) => row.querySelector?.("th,[role='columnheader']"));
    return headerRow ? rowCells(headerRow).map(columnLabel) : [];
  }

  function rowCells(row) {
    const cells = Array.from(row.querySelectorAll(CELL_SELECTOR))
      .filter((cell) => cell.closest?.(ROW_SELECTOR) === row);
    return cells.length ? cells : Array.from(row.children || []);
  }

  function columnLabel(node) {
    return normalizeColumnLabel(node?.getAttribute?.("aria-label") || node?.getAttribute?.("title") || cellText(node));
  }

  function normalizeColumnLabel(value) {
    return compactText(value).replace(/[↑↓↕⇅]+/g, "").replace(/\s*[（(]元[）)]\s*$/g, "").trim();
  }

  function cellText(node) {
    return compactText(node?.innerText || node?.textContent);
  }

  function metricCells(headers, values) {
    const records = [];
    for (let index = 0; index < Math.min(headers.length, values.length); index += 1) {
      const label = normalizeColumnLabel(headers[index]);
      if (PLAN_METADATA_LABELS.has(label)) continue;
      const record = metricRecord(label, values[index]);
      if (record && (Number.isFinite(record.numericValue) || record.value === "--")) records.push(record);
    }
    return records.slice(0, 24);
  }

  function metricFromPairs(pairs, labels) {
    for (const item of pairs) {
      for (const label of labels) {
        const match = item.rawValue.match(new RegExp(`${escapeRegExp(label)}\\s*[：:]?\\s*(-?[\\d,]+(?:\\.\\d+)?)`, "i"));
        if (match) return Number(match[1].replace(/,/g, ""));
      }
    }
    return null;
  }

  function extractPlanName(value, id) {
    const beforeId = compactText(value).split(new RegExp(`(?:计划)?ID\\s*[：:]?\\s*${escapeRegExp(id)}`, "i"))[0] || "";
    return beforeId.replace(/^(?:投放中|已暂停|暂停中|已关闭)\s*/g, "").trim().slice(0, 120) || `计划 ${id}`;
  }

  function extractPageUpdatedText(doc = document) {
    const text = compactText(doc.body?.innerText || "");
    return text.match(/\b\d{2}-\d{2}\s+\d{2}:\d{2}\s*更新/)?.[0] || "";
  }

  function extractMetric(lines, label) {
    for (let index = 0; index < lines.length; index += 1) {
      const line = lines[index];
      if (line !== label && !line.startsWith(`${label} `) && !line.startsWith(`${label}：`) && !line.startsWith(`${label}:`)) continue;
      const inlineValue = metricValue(line.slice(label.length));
      const value = inlineValue || lines.slice(index + 1, index + 5).map(metricValue).find(Boolean);
      if (!value) continue;
      return metricRecord(label, value);
    }
    return null;
  }

  function metricValue(value) {
    const match = compactText(value).match(/(?:[¥￥]\s*)?(-?(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?%?|--)/);
    return match?.[1] || "";
  }

  function metricRecord(label, rawValue) {
    const value = metricValue(rawValue) || compactText(rawValue);
    if (!value) return null;
    const metric = { label, value };
    const numericValue = Number(value.replace(/[%￥¥,]/g, ""));
    if (Number.isFinite(numericValue)) metric.numericValue = numericValue;
    return metric;
  }

  function normalizeMetricRecord(value) {
    const label = normalizeColumnLabel(value?.label);
    const raw = value?.value ?? value?.numericValue;
    return label ? metricRecord(label, raw) : null;
  }

  function escapeRegExp(value) {
    return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  }

  function cleanAccountKey(value) {
    const text = compactText(value);
    return /^[A-Za-z0-9_.:@-]{3,128}$/.test(text) ? text : "";
  }

  const api = {
    classifySignals,
    detectPageContext,
    classifyLocation,
    extractAccountKey,
    detectAccountKey,
    extractAccountName,
    detectAccountName,
    extractPageData,
    detectPageData,
    extractSummaryMetrics,
    extractPlanTotals,
    extractPlanRows,
    buildPlanRow,
    extractPageUpdatedText
  };
  if (typeof window !== "undefined") window.MMWQianchuanPageContext = api;
  if (typeof module !== "undefined" && module.exports) module.exports = api;
})();
