(() => {
  const GUARD = "__MMW_ECOMMERCE_FLOW_RECORDER_CONTENT__";
  if (globalThis[GUARD]) return;
  globalThis[GUARD] = true;

  const ACTIONS = {
    start: "MMW_ECOMMERCE_FLOW_RECORDER_START",
    stopExport: "MMW_ECOMMERCE_FLOW_RECORDER_STOP_EXPORT",
    exportLast: "MMW_ECOMMERCE_FLOW_RECORDER_EXPORT_LAST",
    status: "MMW_ECOMMERCE_FLOW_RECORDER_STATUS",
    event: "MMW_ECOMMERCE_FLOW_RECORDER_EVENT"
  };
  const ROOT_ID = "mmw-ecommerce-flow-recorder-root";
  const TOOLBAR_ID = "mmw-commerce";
  const isTopFrame = (() => {
    try { return window.top === window; } catch (_) { return true; }
  })();
  const state = { active: false, eventCount: 0, hasTrace: false, busy: false, message: "" };
  let root = null;
  let shadow = null;
  let lastDialogSignature = "";
  let statusTimer = 0;

  function redactText(value, limit = 180) {
    return String(value ?? "")
      .replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [REDACTED]")
      .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[EMAIL]")
      .replace(/(?<!\d)1[3-9]\d{9}(?!\d)/g, "[PHONE]")
      .replace(/\s+/g, " ")
      .trim()
      .slice(0, limit);
  }

  function sanitizeUrl(value) {
    try {
      const url = new URL(String(value || ""), location.href);
      const sensitive = /authorization|cookie|token|password|secret|session|ticket|sign/i;
      return {
        scheme: url.protocol.replace(":", ""),
        host: url.host,
        path: url.pathname.replace(/[0-9a-f]{8}-[0-9a-f-]{27,}/gi, ":uuid").replace(/(?<=\/|=)\d{7,}(?=\/|$)/g, ":id").slice(0, 420),
        queryKeys: Array.from(new Set(Array.from(url.searchParams.keys()).filter((key) => !sensitive.test(key)))).slice(0, 80)
      };
    } catch (_) {
      return { scheme: "", host: "", path: redactText(value, 220), queryKeys: [] };
    }
  }

  function send(message) {
    return chrome.runtime.sendMessage(message).catch((error) => ({ ok: false, error: error?.message || String(error) }));
  }

  function record(category, name, data = {}) {
    if (!state.active) return;
    send({ type: ACTIONS.event, category, name, data }).catch(() => {});
  }

  function elementDescriptor(target) {
    const element = target instanceof Element ? target : target?.parentElement;
    if (!element || element.closest?.(`[data-mmw-flow-recorder-ui="true"]`)) return null;
    const actionable = element.closest?.("button,a,input,select,textarea,[role='button'],[role='tab'],[role='menuitem'],[data-action]") || element;
    const label = actionable.getAttribute?.("aria-label")
      || actionable.getAttribute?.("title")
      || actionable.labels?.[0]?.textContent
      || actionable.closest?.("label")?.textContent
      || "";
    const descriptor = {
      tag: String(actionable.tagName || "").toLowerCase(),
      role: String(actionable.getAttribute?.("role") || ""),
      inputType: String(actionable.getAttribute?.("type") || ""),
      id: redactText(actionable.id || "", 80),
      name: redactText(actionable.getAttribute?.("name") || "", 80),
      classes: Array.from(actionable.classList || []).slice(0, 8).map((item) => redactText(item, 60)),
      text: redactText(actionable.textContent || actionable.value || "", 140),
      label: redactText(label, 140)
    };
    const href = actionable.getAttribute?.("href");
    if (href) descriptor.href = sanitizeUrl(href);
    if (/password/i.test(descriptor.inputType) || /password|token|secret/i.test(descriptor.name)) descriptor.text = "[REDACTED]";
    return descriptor;
  }

  function storageSnapshot(storage) {
    const sensitive = /authorization|cookie|token|password|passwd|secret|credential|csrf|xsrf|ticket|signature|access[_-]?key|private[_-]?key/i;
    const business = /account|user|member|shop|store|tenant|merchant|platform|feature|permission|entitlement|profile|workspace|role|points|balance|plan/i;
    const keys = [];
    const businessValues = {};
    try {
      for (let index = 0; index < Math.min(storage.length, 300); index += 1) {
        const key = String(storage.key(index) || "");
        if (!key) continue;
        keys.push(redactText(key, 120));
        if (sensitive.test(key) || !business.test(key)) continue;
        const rawValue = String(storage.getItem(key) || "").slice(0, 20000);
        try { businessValues[key] = JSON.parse(rawValue); } catch (_) { businessValues[key] = rawValue; }
      }
    } catch (_) {}
    return { keys: keys.slice(0, 300), businessValues };
  }

  function sessionSnapshot() {
    let cookieNames = [];
    let localStorageState = { keys: [], businessValues: {} };
    let sessionStorageState = { keys: [], businessValues: {} };
    try { localStorageState = storageSnapshot(window.localStorage); } catch (_) {}
    try { sessionStorageState = storageSnapshot(window.sessionStorage); } catch (_) {}
    try {
      cookieNames = document.cookie.split(";").map((item) => redactText(item.split("=")[0], 120)).filter(Boolean).slice(0, 120);
    } catch (_) {}
    return {
      localStorage: localStorageState,
      sessionStorage: sessionStorageState,
      documentCookieNames: cookieNames
    };
  }

  function pageSnapshot() {
    const dialogs = Array.from(document.querySelectorAll("[role='dialog'],.el-dialog,.vxe-modal--box,.custom-dialog,.frame-dialog"))
      .filter((element) => {
        const style = getComputedStyle(element);
        return style.display !== "none" && style.visibility !== "hidden";
      })
      .slice(0, 5)
      .map((element) => ({
        title: redactText(element.querySelector("[class*='title'],h1,h2,h3")?.textContent || "", 140),
        text: redactText(element.textContent || "", 220),
        classes: Array.from(element.classList || []).slice(0, 8)
      }));
    return {
      url: sanitizeUrl(location.href),
      title: redactText(document.title, 160),
      visibility: document.visibilityState,
      dialogs,
      session: sessionSnapshot()
    };
  }

  function applyStatus(next = {}) {
    state.active = next.active === true;
    state.eventCount = Number(next.eventCount || 0);
    state.hasTrace = next.hasTrace === true || state.eventCount > 0;
    render();
    scheduleStatusRefresh();
  }

  async function refreshStatus() {
    const response = await send({ type: ACTIONS.status });
    if (response?.ok) applyStatus(response);
  }

  function scheduleStatusRefresh() {
    clearTimeout(statusTimer);
    statusTimer = window.setTimeout(refreshStatus, state.active ? 1200 : 2600);
  }

  function toolbarRect() {
    const host = document.getElementById(TOOLBAR_ID);
    const toolbar = host?.shadowRoot?.querySelector(".mcjApp") || host;
    if (!toolbar) return null;
    const rect = toolbar.getBoundingClientRect();
    return rect.width > 10 && rect.height > 10 ? rect : null;
  }

  function ensureUi() {
    if (!isTopFrame || root?.isConnected) return;
    root = document.createElement("div");
    root.id = ROOT_ID;
    root.dataset.mmwFlowRecorderUi = "true";
    shadow = root.attachShadow({ mode: "open" });
    (document.documentElement || document.body).appendChild(root);
  }

  function positionUi() {
    if (!root) return;
    const rect = toolbarRect();
    root.style.position = "fixed";
    root.style.zIndex = "2147483000";
    if (rect) {
      root.style.left = `${Math.min(window.innerWidth - 190, Math.max(12, rect.right + 8))}px`;
      root.style.top = `${Math.max(12, rect.top + 8)}px`;
      root.style.bottom = "auto";
    } else {
      root.style.left = "16px";
      root.style.top = "auto";
      root.style.bottom = "92px";
    }
  }

  function render() {
    if (!isTopFrame) return;
    const visible = state.active || Boolean(toolbarRect());
    if (!visible) {
      if (root) root.style.display = "none";
      return;
    }
    ensureUi();
    root.style.display = "block";
    positionUi();
    const active = state.active;
    shadow.innerHTML = `
      <style>
        :host{all:initial}
        .panel{box-sizing:border-box;width:${active ? 208 : 126}px;padding:10px;border:1px solid rgba(117,164,225,.56);border-radius:12px;background:rgba(245,250,255,.9);box-shadow:0 12px 32px rgba(30,76,137,.2);backdrop-filter:blur(16px) saturate(1.15);font-family:"Microsoft YaHei UI","Microsoft YaHei",sans-serif;color:#17355f}
        .head{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:800}.dot{width:8px;height:8px;border-radius:50%;background:${active ? "#ef5b5b" : "#2f79d9"};box-shadow:0 0 0 4px ${active ? "rgba(239,91,91,.13)" : "rgba(47,121,217,.12)"}}
        .meta{margin:7px 0 9px;color:#657995;font-size:11px;line-height:1.45}.actions{display:flex;gap:6px;flex-wrap:wrap}
        button{height:30px;border:1px solid #8db4e8;border-radius:8px;background:#fff;color:#24518f;font-size:12px;font-weight:700;cursor:pointer}button:hover{background:#eaf3ff}button.primary{flex:1;background:#2f79d9;color:#fff;border-color:#2f79d9}button.danger{flex:1;background:#fff3f3;color:#c13f3f;border-color:#ef9c9c}button:disabled{opacity:.55;cursor:wait}
        .message{margin-top:7px;color:#b34242;font-size:11px;line-height:1.4}
      </style>
      <div class="panel" data-mmw-flow-recorder-ui="true">
        <div class="head"><span class="dot"></span><span>${active ? "搬家监听中" : "搬家流程监听"}</span></div>
        ${active ? `<div class="meta">已记录 ${state.eventCount} 个结构事件<br>不保存密码、令牌和输入原文</div>` : `<div class="meta">运行完整搬家流程后导出 JSON</div>`}
        <div class="actions">
          ${active
            ? `<button data-action="checkpoint" type="button">记录节点</button><button class="danger" data-action="stop" type="button">结束并导出</button>`
            : `<button class="primary" data-action="start" type="button">开始监听</button>${state.hasTrace ? `<button data-action="export" type="button">导出上次</button>` : ""}`}
        </div>
        ${state.message ? `<div class="message">${redactText(state.message, 160)}</div>` : ""}
      </div>
    `;
    shadow.querySelectorAll("button").forEach((button) => {
      button.disabled = state.busy;
      button.addEventListener("click", () => handleAction(button.dataset.action));
    });
  }

  async function handleAction(action) {
    if (state.busy) return;
    state.busy = true;
    state.message = "";
    render();
    try {
      if (action === "start") {
        const response = await send({ type: ACTIONS.start });
        if (!response?.ok) throw new Error(response?.error || "启动监听失败");
        applyStatus(response);
        record("checkpoint", "initial-page-snapshot", pageSnapshot());
      } else if (action === "stop") {
        record("checkpoint", "final-page-snapshot", pageSnapshot());
        const response = await send({ type: ACTIONS.stopExport });
        if (!response?.ok) throw new Error(response?.error || "导出监听记录失败");
        state.active = false;
        state.hasTrace = true;
        state.message = `已导出 ${response.eventCount || 0} 条记录`;
      } else if (action === "export") {
        const response = await send({ type: ACTIONS.exportLast });
        if (!response?.ok) throw new Error(response?.error || "导出上次记录失败");
        state.message = `已重新导出 ${response.eventCount || 0} 条记录`;
      } else if (action === "checkpoint") {
        record("checkpoint", "manual-checkpoint", pageSnapshot());
        state.message = "已记录当前页面节点";
      }
    } catch (error) {
      state.message = error?.message || String(error);
    } finally {
      state.busy = false;
      render();
      scheduleStatusRefresh();
    }
  }

  document.addEventListener("click", (event) => {
    const descriptor = elementDescriptor(event.target);
    if (descriptor) record("interaction", "click", descriptor);
  }, true);

  document.addEventListener("change", (event) => {
    const descriptor = elementDescriptor(event.target);
    if (!descriptor) return;
    const target = event.target;
    descriptor.valueLength = typeof target?.value === "string" ? target.value.length : 0;
    if (target instanceof HTMLSelectElement) descriptor.selectedText = redactText(target.selectedOptions?.[0]?.textContent || "", 120);
    record("interaction", "change", descriptor);
  }, true);

  window.addEventListener("message", (event) => {
    if (!state.active || event.source !== window || !event.data || typeof event.data !== "object") return;
    const type = String(event.data.type || event.data.action || event.data.name || "");
    const source = String(event.data.source || "");
    if (!/MMW|mcj|ecommerce|shop.?move|goods/i.test(`${source} ${type}`)) return;
    record("runtime", "window-message", {
      source: redactText(source, 100),
      action: redactText(type, 140),
      fields: Object.keys(event.data).filter((key) => !/token|cookie|password|secret|authorization/i.test(key)).slice(0, 80),
      payload: event.data
    });
  });

  window.addEventListener("popstate", () => record("navigation", "page-popstate", pageSnapshot()));
  window.addEventListener("hashchange", () => record("navigation", "page-hashchange", pageSnapshot()));
  window.addEventListener("pagehide", () => record("navigation", "page-hide", pageSnapshot()));
  document.addEventListener("visibilitychange", () => record("page", "visibility-changed", pageSnapshot()));

  function observeDialogs() {
    const target = document.documentElement;
    if (!target) return;
    const observer = new MutationObserver(() => {
      if (!state.active) {
        render();
        return;
      }
      const snapshot = pageSnapshot();
      const signature = JSON.stringify(snapshot.dialogs);
      if (signature !== lastDialogSignature) {
        lastDialogSignature = signature;
        if (snapshot.dialogs.length) record("page", "dialog-state-changed", snapshot);
      }
      render();
    });
    observer.observe(target, { childList: true, subtree: true });
  }

  chrome.runtime.onMessage.addListener((message) => {
    if (message?.type !== "MMW_ECOMMERCE_FLOW_RECORDER_STATE") return false;
    applyStatus(message);
    return false;
  });

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", () => {
      observeDialogs();
      render();
      if (state.active) record("page", "document-ready", pageSnapshot());
    }, { once: true });
  } else {
    observeDialogs();
  }
  window.addEventListener("resize", render, { passive: true });
  refreshStatus();
})();
