(() => {
  if (window.top !== window || window.__MMW_DAREN_INVITE_V5__) return;
  window.__MMW_DAREN_INVITE_V5__ = true;

  const IDS = {
    topButton: "mmwDarenInviteTopButton",
    topSlot: "mmwDarenInviteTopSlot",
    overlay: "mmwDarenInviteOverlay",
    status: "mmwDarenInviteStatusText",
    toast: "mmwDarenInviteToast",
    loaderCard: "mmwDarenInviteLoaderCard",
    sendCard: "mmwDarenInviteSendCard",
    count: "mmwDarenInviteCountText",
    filtered: "mmwDarenInviteFilteredText",
    selected: "mmwDarenInviteSelectedText",
    selectAll: "mmwDarenInviteSelectAll",
    tableBody: "mmwDarenInviteTableBody",
    columnSettings: "mmwDarenInviteColumnSettings",
    filteredBody: "mmwDarenInviteFilteredBody",
    loadButton: "mmwDarenInviteLoadButton",
    resetButton: "mmwDarenInviteResetButton",
    openSendButton: "mmwDarenInviteOpenSendButton",
    sendButton: "mmwDarenInviteSendButton",
    inviteText: "mmwDarenInviteText",
    phone: "mmwDarenInvitePhone",
    wechat: "mmwDarenInviteWechat",
    commissionRatio: "mmwDarenInviteCommissionRatio",
    interval: "mmwDarenInviteInterval",
    findKeyword: "mmwDarenInviteFindKeyword",
    sortField: "mmwDarenInviteSortField",
    sortType: "mmwDarenInviteSortType",
    similarKeyword: "mmwDarenInviteSimilarKeyword",
    productKeyword: "mmwDarenInviteProductKeyword",
    storeProductQuery: "mmwDarenInviteStoreProductQuery"
  };

  const AUTH_KEY = "pluginAuth";
  const INTERVAL_KEY = "mmwInviteIntervalSeconds";
  const FORM_KEY = "mmwDarenInviteFormV4";
  const LEGACY_FORM_KEYS = ["mmwDarenInviteFormV3"];
  const ICON_URL = chrome.runtime.getURL("icon32.png");
  const DAREN_SQUARE_PATH = "/dashboard/servicehall/daren-square";
  const MAX_LOAD_PAGE = 120;
  const LOAD_PAGE_DELAY_MS = 1500;
  const DEFAULT_INVITE_TEXT = "你好，我们正在寻找优质达人合作带货，看到你的账号内容和粉丝匹配度都不错，想邀请你一起合作。欢迎查看邀约商品，有意向可以直接回复沟通。";
  const MAX_INVITE_PRODUCTS = 5;
  const STORE_PRODUCT_PAGE_SIZE = 20;

  const MODES = Object.freeze({
    FIND_DAREN: "find_daren",
    PRD_2_KOL: "prd_2_kol",
    SIMILAR_KOL: "similar_kol",
    REC_LIST: "rec_list"
  });

  const MODE_LABELS = {
    [MODES.FIND_DAREN]: "找达人",
    [MODES.PRD_2_KOL]: "按商品找达人",
    [MODES.SIMILAR_KOL]: "找相似达人",
    [MODES.REC_LIST]: "按人群包找达人"
  };

  const PUBLIC_FILTER_FIELDS = Object.freeze({
    contentType: "content_type",
    merchantInfo: "merchant_info",
    mainCateNew: "main_cate_new",
    cateFirst: "common_selection_first_cate_code",
    cateSecond: "common_selection_second_cate_code",
    cateThird: "common_selection_third_cate_code",
    authorLocation: "author_location",
    fansCity: "common_selection_fans_city_code"
  });

  const CONTENT_TYPES = [
    { value: 1, label: "全部达人" },
    { value: 3, label: "视频达人" },
    { value: 2, label: "直播达人" },
    { value: 4, label: "图文达人" },
    { value: 5, label: "橱窗达人" }
  ];

  const SORT_FIELDS = {
    1: [
      { label: "粉丝数", value: 1 },
      { label: "销售总额", value: 21 },
      { label: "直播销售总额", value: 22 },
      { label: "视频销售总额", value: 23 },
      { label: "图文销售总额", value: 24 },
      { label: "橱窗销售总额", value: 25 }
    ],
    2: [
      { label: "粉丝数", value: 1 },
      { label: "直播销售总额", value: 22 },
      { label: "场均直播销售额", value: 14 },
      { label: "直播观看次数", value: 26 },
      { label: "直播 GPM", value: 17 }
    ],
    3: [
      { label: "粉丝数", value: 1 },
      { label: "视频销售总额", value: 23 },
      { label: "单视频销售总额", value: 18 },
      { label: "视频观看次数", value: 19 },
      { label: "视频 GPM", value: 20 }
    ],
    4: [
      { label: "粉丝数", value: 1 },
      { label: "图文销售总额", value: 24 },
      { label: "单图文销售额", value: 27 },
      { label: "图文观看次数", value: 28 },
      { label: "图文 GPM", value: 29 }
    ],
    5: [
      { label: "粉丝数", value: 1 },
      { label: "橱窗销售总额", value: 25 },
      { label: "橱窗订单数", value: 30 }
    ]
  };

  const SORT_TYPES = [
    { label: "从低到高", value: 0 },
    { label: "从高到低", value: 1 }
  ];

  const INTERVAL_OPTIONS = [3, 5, 10, 15, 30, 45, 60, 120];

  const RIGHTS_OPTIONS = [
    "专属高佣",
    "免费申样",
    "视频素材支持",
    "优质视频投流"
  ];

  const TALENT_TABLE_COLUMNS = [
    { key: "talent", label: "达人信息", index: 3 },
    { key: "fans", label: "粉丝数", index: 4 },
    { key: "settlement", label: "结算总额", index: 5 },
    { key: "liveSettlement", label: "直播结算总额", index: 6 },
    { key: "videoSettlement", label: "视频结算总额", index: 7 },
    { key: "imageTextSettlement", label: "图文结算总额", index: 8 },
    { key: "result", label: "处理结果", index: 9 }
  ];
  const DEFAULT_TALENT_TABLE_COLUMNS = Object.freeze(Object.fromEntries(
    TALENT_TABLE_COLUMNS.map((column) => [column.key, true])
  ));

  const API = {
    searchAuthor: "/square_pc_api/square/search_feed_author",
    publicFilterSchema: "/square_pc_api/square/filter",
    similarSuggest: "/square_pc_api/similar_kol/familiar_sug",
    similarSearchSuggest: "/square_pc_api/square/sug?sug_source=1",
    similarList: "/square_pc_api/similar_kol/list",
    productSuggest: "/square_pc_api/prd_2_kol/card_sug",
    productSearchSuggest: "/square_pc_api/recommend/rec_promotion_product",
    productList: "/square_pc_api/prd_2_kol/list",
    recListSchema: "/square_pc_api/recommend/rec_author_filter",
    recListSearch: "/square_pc_api/recommend/crowd_pack_rec_author",
    senderMsg: "/connection/pc/im/card/sender/msg",
    promotionList: "/connection/pc/im/promotion/list",
    batchSend: "/connection/pc/im/shangda/msgs/send",
    singleSend: "/connection/pc/im/invite/card/send"
  };

  const COPY = {
    needAuth: "请先登录 MMW工作台账号后再使用达人邀约。",
    notSquare: "请先打开抖店「达人广场」页面。",
    requestTimeout: "抖店请求超时，请确认页面已登录并刷新后重试。",
    dialogTitle: "MMWGZT 达人邀约",
    dialogDesc: "对齐哈士奇的达人筛选、邀约权益与商品推荐逻辑，按真实抖店接口加载与发送。",
    topButton: "达人邀约",
    serviceText: "客服",
    close: "关闭",
    statusReady: "准备好了，先设置筛选条件，再点击“开始加载”。",
    statusLoading: "正在从抖店接口加载达人…",
    statusNoTargets: "没有加载到可邀约达人，可换条件后重试。",
    statusStopped: "已停止当前任务。",
    statusSending: "正在发送邀约…",
    statusSent: "邀约发送完成。",
    loadStart: "开始加载",
    loadStop: "停止加载",
    loadContinue: "继续加载",
    reset: "清空重载",
    send: "私信邀约",
    sendStop: "停止发送",
    unnamed: "未命名达人"
  };

  const state = {
    auth: null,
    authActive: false,
    modalOpen: false,
    sendDialogOpen: false,
    loading: false,
    sending: false,
    stopRequested: false,
    page: 1,
    total: 0,
    hasMore: true,
    cardVersion: null,
    talents: new Map(),
    filtered: new Map(),
    selected: new Set(),
    requestSeq: 1,
    requestWaiters: new Map(),
    toastTimer: 0,
    routeTimer: 0,
    publicFilterHeaders: [],
    publicFilterLoading: false,
    recListSchema: null,
    recListLoading: false,
    similarSuggestList: [],
    productSuggestList: [],
    similarSearchResults: [],
    productSearchResults: [],
    similarSearchId: "",
    storeProducts: [],
    storeProductPage: 1,
    storeProductHasMore: true,
    storeProductsLoading: false,
    form: createDefaultForm()
  };

  onReady(init);

  async function init() {
    cleanupLegacyMounts();
    state.auth = await readAuthState();
    state.authActive = isAuthActive(state.auth);
    state.form = await readFormState();
    state.form.intervalSeconds = await readIntervalState(state.form.intervalSeconds);
    bindGlobalEvents();
    ensureTopButton();
    observeDom();
    await checkPendingOpen();
  }

  function createDefaultForm() {
    return {
      activeMode: MODES.FIND_DAREN,
      expandedGroupsVersion: 2,
      expandedGroups: {},
      inviteText: DEFAULT_INVITE_TEXT,
      phone: "",
      wechat: "",
      rights: [],
      commissionRatio: "",
      intervalSeconds: 5,
      storeProductQuery: "",
      selectedProducts: [],
      talentColumns: { ...DEFAULT_TALENT_TABLE_COLUMNS },
      manualProductIdsText: "",
      legacyCategoryIdsText: "",
      modes: {
        [MODES.FIND_DAREN]: {
          query: "",
          type: 1,
          sort_field: "",
          sort_type: "",
          filters: {},
          cascadePaths: {}
        },
        [MODES.SIMILAR_KOL]: {
          query: "",
          author_name: "",
          search_text: "",
          req_source: 1,
          filters: {},
          cascadePaths: {}
        },
        [MODES.PRD_2_KOL]: {
          pid: "",
          product_name: "",
          search_text: "",
          filters: {},
          cascadePaths: {}
        },
        [MODES.REC_LIST]: {
          author_type: [],
          target_crowd: [],
          matching_method: [],
          main_cate: []
        }
      }
    };
  }

  function cleanupLegacyMounts() {
    [
      "mmwInviteBackdrop",
      "mmwInviteShell",
      "mmwInviteToast",
      "mmwInviteTopButtonSlot",
      IDS.overlay,
      IDS.topSlot,
      IDS.toast
    ].forEach((id) => document.getElementById(id)?.remove());
    document.documentElement.classList.remove("mmwInviteLocked", "mmwDarenInviteLocked");
    document.body.classList.remove("mmwInviteLocked", "mmwDarenInviteLocked");
  }

  function bindGlobalEvents() {
    window.addEventListener("message", handleWindowMessage, false);
    document.addEventListener("keydown", (event) => {
      if (event.key !== "Escape") return;
      if (state.sendDialogOpen && !state.sending) {
        state.sendDialogOpen = false;
        renderSendCard();
        syncButtons();
        return;
      }
      if (state.modalOpen) closeModal();
    });

    chrome.storage.onChanged.addListener((changes, areaName) => {
      if (areaName !== "local") return;
      if (changes[AUTH_KEY]) {
        state.auth = changes[AUTH_KEY].newValue || null;
        state.authActive = isAuthActive(state.auth);
      }
      if (changes[INTERVAL_KEY]) {
        state.form.intervalSeconds = normalizeInterval(changes[INTERVAL_KEY].newValue);
        syncButtons();
      }
    });

    patchHistoryListener();
  }

  function handleWindowMessage(event) {
    if (event.source !== window) return;

    const data = event.data;
    if (data?.action === "response" && data.data?.uuid) {
      const waiter = state.requestWaiters.get(data.data.uuid);
      if (!waiter) return;
      state.requestWaiters.delete(data.data.uuid);
      window.clearTimeout(waiter.timer);
      debugInviteLog("xrequest response", {
        uuid: data.data.uuid,
        result: summarizeXRequestResult(data.data.result)
      });
      waiter.resolve(data.data.result);
      return;
    }

    const action = String(data?.action || "").trim();
    if (action === "trigger-main-drawer" || action === "trigger-find-talent-drawer") {
      requestOpen("插件联动入口");
    }
  }

  function patchHistoryListener() {
    const notify = () => {
      window.clearTimeout(state.routeTimer);
      state.routeTimer = window.setTimeout(ensureTopButton, 260);
    };

    ["pushState", "replaceState"].forEach((name) => {
      const native = history[name];
      if (typeof native !== "function" || native.__mmwDarenInvitePatched) return;
      const patched = function(...args) {
        const result = native.apply(this, args);
        notify();
        return result;
      };
      patched.__mmwDarenInvitePatched = true;
      history[name] = patched;
    });

    window.addEventListener("popstate", notify);
  }

  function observeDom() {
    const observer = new MutationObserver(() => ensureTopButton());
    observer.observe(document.documentElement, { childList: true, subtree: true });
  }

  async function checkPendingOpen() {
    const response = await chrome.runtime.sendMessage({
      name: "newPageTask",
      body: { action: "get-task", name: "open-daren-invite" }
    }).catch(() => null);

    const tasks = Array.isArray(response) ? response : [];
    if (tasks.some((task) => task?.open)) requestOpen("首页卡片入口");
  }

  async function requestOpen(source) {
    if (!isDarenSquarePage()) {
      toast(COPY.notSquare);
      return;
    }
    if (!await ensureAccess()) return;
    openModal(source);
  }

  async function ensureAccess() {
    if (state.authActive) return true;
    state.auth = await readAuthState();
    state.authActive = isAuthActive(state.auth);
    if (state.authActive) return true;
    toast(COPY.needAuth);
    return false;
  }

  function ensureTopButton() {
    if (!isDarenSquarePage()) {
      document.getElementById(IDS.topSlot)?.remove();
      return;
    }

    let slot = document.getElementById(IDS.topSlot);
    if (!slot) {
      slot = document.createElement("div");
      slot.id = IDS.topSlot;
      slot.className = "mmwInviteTopSlot";
      slot.appendChild(createTopButton());
    }

    const anchor = findTopButtonAnchor();
    if (anchor?.parentElement) {
      slot.classList.remove("mmwInviteTopSlot--fallback");
      if (slot.previousElementSibling !== anchor) {
        anchor.insertAdjacentElement("afterend", slot);
      }
      return;
    }

    const nav = findTopNavContainer();
    if (nav) {
      slot.classList.remove("mmwInviteTopSlot--fallback");
      if (slot.parentElement !== nav) {
        nav.appendChild(slot);
      }
      return;
    }

    const menu = document.querySelector(".auxo-menu-overflow");
    if (menu instanceof HTMLElement) {
      slot.classList.remove("mmwInviteTopSlot--fallback");
      menu.appendChild(slot);
      return;
    }

    if (slot.parentElement === document.body) return;
    slot.classList.add("mmwInviteTopSlot--fallback");
    document.body.appendChild(slot);
  }

  function createTopButton() {
    const button = document.createElement("button");
    button.id = IDS.topButton;
    button.type = "button";
    button.className = "mmwInviteTopButton";
    button.innerHTML = `<img src="${ICON_URL}" alt=""><span>${COPY.topButton}</span>`;
    button.addEventListener("click", () => requestOpen("达人广场按钮"));
    return button;
  }

  function findTopButtonAnchor() {
    const anchors = Array.from(document.querySelectorAll("a,button,div,span"))
      .filter((node) => node instanceof HTMLElement)
      .map((node) => {
        if (node.id === IDS.topButton || node.closest(`#${IDS.topSlot}`)) return false;
        if (normalizeText(node.textContent) !== "看数据") return false;
        const item = liftTopNavItem(node);
        const rect = item.getBoundingClientRect();
        if (item.id === IDS.topButton || item.closest(`#${IDS.topSlot}`)) return false;
        if (normalizeText(item.textContent) !== "看数据") return false;
        return rect.top >= 0 && rect.top <= 130 && rect.width > 20 && rect.height > 20 ? item : false;
      })
      .filter(Boolean);
    return anchors[anchors.length - 1] || null;
  }

  function liftTopNavItem(node) {
    let item = node;
    let current = node;
    for (let depth = 0; current?.parentElement && depth < 5; depth += 1) {
      const parent = current.parentElement;
      const text = normalizeText(parent.textContent);
      const rect = parent.getBoundingClientRect();
      const isNavItem = parent.matches("a,button,[role='menuitem']");
      const isCompactTextWrap = text === "看数据" && rect.width <= 140 && rect.height <= 60;
      if (isNavItem || isCompactTextWrap) item = parent;
      if (text !== "看数据" || rect.width > 180 || rect.height > 80) break;
      current = parent;
    }
    return item;
  }

  function findTopNavContainer() {
    const labels = ["首页", "推荐商品", "找达人", "管合作", "看数据"];
    return Array.from(document.querySelectorAll("nav,header,ul,div"))
      .filter((node) => node instanceof HTMLElement)
      .filter((node) => {
        if (node.id === IDS.topButton || node.closest(`#${IDS.topSlot}`)) return false;
        const text = normalizeText(node.textContent);
        if (!labels.every((label) => text.includes(label))) return false;
        const rect = node.getBoundingClientRect();
        return rect.top >= 0 && rect.top <= 90 && rect.width >= 260 && rect.height >= 24 && rect.height <= 80;
      })
      .sort((a, b) => {
        const ar = a.getBoundingClientRect();
        const br = b.getBoundingClientRect();
        return ar.width * ar.height - br.width * br.height;
      })[0] || null;
  }

  function openModal(source) {
    ensureModalShell();
    state.modalOpen = true;
    state.stopRequested = false;
    state.form.activeMode = state.form.activeMode || MODES.FIND_DAREN;
    document.getElementById(IDS.overlay)?.classList.add("is-open");
    document.documentElement.classList.add("mmwDarenInviteLocked");
    document.body.classList.add("mmwDarenInviteLocked");
    renderLoaderCard();
    renderSendCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    syncStatus(`${COPY.statusReady} 来源：${source || "当前页面"}`);
    ensureModalResources().catch(showError);
  }

  function closeModal() {
    document.getElementById(IDS.overlay)?.classList.remove("is-open");
    document.documentElement.classList.remove("mmwDarenInviteLocked");
    document.body.classList.remove("mmwDarenInviteLocked");
    state.modalOpen = false;
    state.sendDialogOpen = false;
    state.stopRequested = true;
    syncAll();
  }

  function ensureModalShell() {
    if (document.getElementById(IDS.overlay)) return;

    const overlay = document.createElement("div");
    overlay.id = IDS.overlay;
    overlay.className = "mmwInviteOverlay";
    overlay.innerHTML = `
      <div class="mmwInviteOverlayDialog">
        <div class="mmwInviteDialog">
          <header class="mmwInviteDialogHeader">
            <div class="mmwInviteHeader">
              <div class="mmwInviteHeaderMain">
                <img src="${ICON_URL}" alt="">
                <div class="mmwInviteHeaderTitle">
                  <div class="gj-title-dd-dia">${COPY.dialogTitle}</div>
                </div>
              </div>
              <div class="mmwInviteHeaderAside">
                <button class="mmwInviteCloseButton" type="button" data-action="close" aria-label="${COPY.close}">×</button>
              </div>
            </div>
          </header>
          <div class="mmwInviteDialogBody">
            <div class="mmwInviteBody">
              <div class="mmwInviteStatusRow">
                <div class="mmwInviteStatusChip">
                  <span class="mmwInviteStatusDot"></span>
                  <span id="${IDS.status}">${COPY.statusReady}</span>
                </div>
              </div>
              <div class="mmwInvitePanel">
                <div id="${IDS.loaderCard}"></div>
                <div class="mmwInviteWorkspace">
                  <section class="mmwInviteCard mmwInviteTalentCard">
                    <div class="mmwInviteTableToolbar">
                      <div class="mmwInviteTableTools">
                        ${renderTalentColumnSettings()}
                      </div>
                    </div>
                    <div class="mmwInviteTableWrap">
                      <table class="mmwInviteTable mmwInviteTalentTable ${talentTableColumnClass()}">
                        <thead>
                          <tr>
                            <th class="mmwInviteTableColId">ID</th>
                            <th class="mmwInviteTableColCheck">
                              <label class="mmwInviteTableCheckHead">
                                <input id="${IDS.selectAll}" type="checkbox">
                                <span>0/0</span>
                              </label>
                            </th>
                            <th>达人信息</th>
                            <th>粉丝数</th>
                            <th>结算总额</th>
                            <th>直播结算总额</th>
                            <th>视频结算总额</th>
                            <th>图文结算总额</th>
                            <th>处理结果</th>
                          </tr>
                        </thead>
                        <tbody id="${IDS.tableBody}">
                          <tr><td colspan="9" class="mmwInviteEmpty">还没有加载达人</td></tr>
                        </tbody>
                      </table>
                    </div>
                    <details class="mmwInviteFilteredDetails">
                      <summary>查看不可邀约达人</summary>
                      <div class="mmwInviteFilteredWrap">
                        <table class="mmwInviteTable is-filtered">
                          <thead>
                            <tr>
                              <th>达人</th>
                              <th>原因</th>
                            </tr>
                          </thead>
                          <tbody id="${IDS.filteredBody}">
                            <tr><td colspan="2" class="mmwInviteEmpty">暂无过滤记录</td></tr>
                          </tbody>
                        </table>
                      </div>
                    </details>
                  </section>
                  <aside id="${IDS.sendCard}" class="mmwInviteSendDock"></aside>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    `;

    overlay.addEventListener("click", (event) => {
      if (event.target === overlay) closeModal();
    });
    document.body.appendChild(overlay);
    bindPanelEvents(overlay);
  }

  function bindPanelEvents(root) {
    root.addEventListener("click", (event) => {
      const actionTarget = event.target.closest("[data-action]");
      if (!actionTarget) return;
      const { action } = actionTarget.dataset;

      if (action === "close") {
        closeModal();
        return;
      }

      if (action === "switchMode") {
        setActiveMode(actionTarget.dataset.mode);
        return;
      }

      if (action === "toggleGroupExpand") {
        toggleGroupExpanded(actionTarget.dataset.groupKey, actionTarget.getAttribute("aria-expanded") === "true");
        return;
      }

      if (action === "setContentType") {
        const form = getModeForm(MODES.FIND_DAREN);
        form.type = Number(actionTarget.dataset.value || 1);
        form.sort_field = "";
        form.sort_type = "";
        resetTalentState();
        renderLoaderCard();
        syncAll();
        saveFormState();
        return;
      }

      if (action === "loadTalents") {
        if (state.loading) {
          state.stopRequested = true;
          syncStatus(COPY.statusStopped);
          syncButtons();
          return;
        }
        handleLoadTalents().catch(showError);
        return;
      }

      if (action === "resetTalents") {
        if (state.loading || state.sending) return;
        resetTalentState();
        renderTalentTable();
        renderFilteredTable();
        syncAll();
        syncStatus("已清空结果，可重新加载。");
        return;
      }

      if (action === "sendInvites") {
        if (state.sending) {
          state.stopRequested = true;
          syncStatus(COPY.statusStopped);
          syncButtons();
          return;
        }
        handleSendInvites().catch(showError);
        return;
      }

      if (action === "openSendDialog") {
        if (state.selected.size === 0) {
          toast("请先勾选要邀约的达人。");
          return;
        }
        state.sendDialogOpen = true;
        renderSendCard();
        syncButtons();
        document.getElementById(IDS.sendCard)?.scrollIntoView({ block: "nearest", inline: "nearest" });
        return;
      }

      if (action === "closeSendDialog") {
        if (state.sending) return;
        state.sendDialogOpen = false;
        renderSendCard();
        syncButtons();
        return;
      }

      if (action === "toggleColumnSettings") {
        toggleColumnSettings();
        return;
      }

      if (action === "toggleTalentColumn") {
        if (!(actionTarget instanceof HTMLInputElement)) return;
        setTalentColumnVisible(actionTarget.dataset.columnKey, actionTarget.checked);
        return;
      }

      if (action === "resetTalentColumns") {
        state.form.talentColumns = { ...DEFAULT_TALENT_TABLE_COLUMNS };
        syncTalentColumnSettings();
        applyTalentColumnVisibility();
        saveFormState();
        return;
      }

      if (action === "togglePublicFilter") {
        if (actionTarget.dataset.disabled === "1") return;
        const mode = actionTarget.dataset.mode;
        const field = actionTarget.dataset.field;
        const value = decodeValueByType(actionTarget.dataset.value, actionTarget.dataset.valueType);
        const kind = actionTarget.dataset.kind || "multi";
        togglePublicFilter(mode, field, value, kind);
        return;
      }

      if (action === "clearCascade") {
        clearCascadeFilter(actionTarget.dataset.mode, actionTarget.dataset.headerKey);
        return;
      }

      if (action === "toggleRecFilter") {
        if (actionTarget.dataset.disabled === "1") return;
        const field = actionTarget.dataset.field;
        const value = decodeValueByType(actionTarget.dataset.value, actionTarget.dataset.valueType);
        const kind = actionTarget.dataset.kind || "multi";
        toggleRecListFilter(field, value, kind);
        return;
      }

      if (action === "searchSimilarCandidates") {
        searchSimilarCandidates().catch(showError);
        return;
      }

      if (action === "searchProductCandidates") {
        searchProductCandidates().catch(showError);
        return;
      }

      if (action === "selectSimilarCandidate") {
        selectSimilarCandidate(Number(actionTarget.dataset.index || -1), actionTarget.dataset.source || "search");
        return;
      }

      if (action === "selectProductCandidate") {
        selectProductCandidate(Number(actionTarget.dataset.index || -1), actionTarget.dataset.source || "search");
        return;
      }

      if (action === "clearSimilar") {
        const form = getModeForm(MODES.SIMILAR_KOL);
        form.query = "";
        form.author_name = "";
        form.search_text = "";
        state.similarSearchResults = [];
        resetTalentState();
        renderLoaderCard();
        renderTalentTable();
        renderFilteredTable();
        syncAll();
        saveFormState();
        return;
      }

      if (action === "clearProductSeed") {
        const form = getModeForm(MODES.PRD_2_KOL);
        form.pid = "";
        form.product_name = "";
        form.search_text = "";
        state.productSearchResults = [];
        resetTalentState();
        renderLoaderCard();
        renderTalentTable();
        renderFilteredTable();
        syncAll();
        saveFormState();
        return;
      }

      if (action === "searchStoreProducts") {
        loadStoreProducts(true).catch(showError);
        return;
      }

      if (action === "loadMoreStoreProducts") {
        loadStoreProducts(false).catch(showError);
        return;
      }

      if (action === "toggleStoreProduct") {
        toggleSelectedProduct(actionTarget.dataset.productId);
        return;
      }

      if (action === "removeSelectedProduct") {
        removeSelectedProduct(actionTarget.dataset.productId);
        return;
      }
    });

    root.addEventListener("input", (event) => {
      const target = event.target;
      if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement)) return;

      if (target.id === IDS.findKeyword) {
        getModeForm(MODES.FIND_DAREN).query = target.value.trim();
        saveFormState();
        return;
      }

      if (target.id === IDS.similarKeyword) {
        getModeForm(MODES.SIMILAR_KOL).search_text = target.value;
        saveFormState();
        return;
      }

      if (target.id === IDS.productKeyword) {
        getModeForm(MODES.PRD_2_KOL).search_text = target.value;
        saveFormState();
        return;
      }

      if (target.id === IDS.storeProductQuery) {
        state.form.storeProductQuery = target.value;
        saveFormState();
        return;
      }

      if (target.id === IDS.inviteText) {
        state.form.inviteText = target.value;
        saveFormState();
        return;
      }

      if (target.id === IDS.phone) {
        state.form.phone = target.value.trim();
        saveFormState();
        return;
      }

      if (target.id === IDS.wechat) {
        state.form.wechat = target.value.trim();
        saveFormState();
        return;
      }

      if (target.id === IDS.commissionRatio) {
        state.form.commissionRatio = target.value.trim();
        saveFormState();
        return;
      }

      if (target.dataset.role === "selected-product-commission") {
        updateSelectedProductField(target.dataset.productId, "customCommissionRatio", target.value.trim(), false);
      }
    });

    root.addEventListener("change", (event) => {
      const target = event.target;
      if (!(target instanceof HTMLInputElement || target instanceof HTMLSelectElement)) return;

      if (target.id === IDS.selectAll) {
        const checked = Boolean(target.checked);
        state.selected = new Set(checked ? Array.from(state.talents.keys()) : []);
        renderTalentTable();
        syncAll();
        return;
      }

      if (target.dataset.uid) {
        const uid = target.dataset.uid;
        if (!uid) return;
        if (target.checked) state.selected.add(uid);
        else state.selected.delete(uid);
        syncAll();
        return;
      }

      if (target.id === IDS.sortField) {
        const form = getModeForm(MODES.FIND_DAREN);
        form.sort_field = target.value ? Number(target.value) : "";
        if (form.sort_field !== "" && form.sort_type === "") form.sort_type = 1;
        resetTalentState();
        syncAll();
        saveFormState();
        return;
      }

      if (target.id === IDS.sortType) {
        const form = getModeForm(MODES.FIND_DAREN);
        form.sort_type = target.value !== "" ? Number(target.value) : "";
        if (form.sort_type !== "" && form.sort_field === "") {
          const defaultField = (SORT_FIELDS[form.type] || SORT_FIELDS[1] || [])[0];
          form.sort_field = defaultField ? defaultField.value : "";
        }
        resetTalentState();
        syncAll();
        saveFormState();
        return;
      }

      if (target.id === IDS.interval) {
        state.form.intervalSeconds = normalizeInterval(target.value);
        saveFormState();
        syncButtons();
        return;
      }

      if (target.dataset.role === "invite-right") {
        toggleInviteRight(target.value, target.checked, false);
        return;
      }

      if (target.dataset.role === "selected-product-sample") {
        updateSelectedProductField(target.dataset.productId, "author_sample_status", target.checked ? 1 : 0, false);
        return;
      }

      if (target.dataset.role === "public-filter-select") {
        const selectedOption = target.selectedOptions?.[0];
        setPublicFilterSelect(
          target.dataset.mode,
          target.dataset.field,
          selectedOption && selectedOption.value !== "" ? selectedOption.value : "",
          selectedOption?.dataset.valueType
        );
        return;
      }

      if (target.dataset.action === "updateCascade") {
        const selectedOption = target.selectedOptions?.[0];
        updateCascadeFilter(
          target.dataset.mode,
          target.dataset.headerKey,
          Number(target.dataset.level || 0),
          selectedOption && selectedOption.value !== ""
            ? decodeValueByType(selectedOption.value, selectedOption.dataset.valueType)
            : target.value
        );
        return;
      }
    });
  }

  async function ensureModalResources() {
    await ensureModeResources(state.form.activeMode || MODES.FIND_DAREN);
    if (!state.storeProducts.length && !state.storeProductsLoading) {
      loadStoreProducts(true).catch(() => {});
    }
  }

  async function ensureModeResources(mode) {
    if ([MODES.FIND_DAREN, MODES.SIMILAR_KOL, MODES.PRD_2_KOL].includes(mode)) {
      await ensurePublicFilterSchema();
      if (mode === MODES.SIMILAR_KOL && !state.similarSuggestList.length) {
        await loadSimilarSuggestions();
      }
      if (mode === MODES.PRD_2_KOL && !state.productSuggestList.length) {
        await loadProductSuggestions();
      }
    }

    if (mode === MODES.REC_LIST) {
      await ensureRecListSchema();
    }
  }

  async function ensurePublicFilterSchema() {
    if (state.publicFilterHeaders.length || state.publicFilterLoading) return;
    state.publicFilterLoading = true;
    renderLoaderCard();
    try {
      const data = await douDianRequest("GET", API.publicFilterSchema, { type: 1 });
      state.publicFilterHeaders = Array.isArray(data?.headers) ? data.headers : [];
      if (state.publicFilterHeaders.length) {
        const defaults = buildDefaultPublicFilters(state.publicFilterHeaders);
        [MODES.FIND_DAREN, MODES.SIMILAR_KOL, MODES.PRD_2_KOL].forEach((mode) => {
          const form = getModeForm(mode);
          form.filters = mergeFilterDefaults(form.filters, defaults);
          form.cascadePaths = normalizePlainObject(form.cascadePaths);
        });
      }
    } finally {
      state.publicFilterLoading = false;
      renderLoaderCard();
      saveFormState();
    }
  }

  async function ensureRecListSchema() {
    if (state.recListSchema || state.recListLoading) return;
    state.recListLoading = true;
    renderLoaderCard();
    try {
      state.recListSchema = await douDianRequest("GET", API.recListSchema, { tab_type: 3 });
    } finally {
      state.recListLoading = false;
      renderLoaderCard();
    }
  }

  async function loadSimilarSuggestions() {
    const data = await douDianRequest("GET", API.similarSuggest);
    state.similarSuggestList = normalizeSimilarSuggestList(data?.sugList || data?.list || []);
    renderLoaderCard();
  }

  async function loadProductSuggestions() {
    const data = await douDianRequest("POST", API.productSuggest, {});
    const list = Array.isArray(data?.prd_list) ? data.prd_list.map((item) => item?.prd_data || item) : [];
    state.productSuggestList = list.map(normalizeProductCandidate).filter((item) => item.product_id);
    renderLoaderCard();
  }

  function setActiveMode(mode) {
    if (!MODE_LABELS[mode] || state.form.activeMode === mode) return;
    state.form.activeMode = mode;
    state.similarSearchResults = [];
    state.productSearchResults = [];
    state.page = 1;
    state.total = 0;
    state.hasMore = true;
    state.talents.clear();
    state.filtered.clear();
    state.selected.clear();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    syncStatus(`已切换到「${MODE_LABELS[mode]}」，请点击“开始加载”。`);
    saveFormState();
    ensureModeResources(mode).catch(showError);
  }

  function getModeForm(mode) {
    return state.form.modes[mode];
  }

  function getExpandedGroups() {
    state.form.expandedGroups = normalizePlainObject(state.form.expandedGroups);
    return state.form.expandedGroups;
  }

  function getDefaultGroupExpanded(groupKey) {
    if (groupKey === "rec:option_headers") return true;
    if (groupKey === "rec:base_headers") return false;
    if (/^public:/.test(String(groupKey || ""))) {
      const matched = String(groupKey || "").match(/:(\d+)$/);
      return matched ? Number(matched[1]) === 0 : true;
    }
    return false;
  }

  function isGroupExpanded(groupKey, fallback = false) {
    const groups = getExpandedGroups();
    if (Object.prototype.hasOwnProperty.call(groups, groupKey)) {
      return Boolean(groups[groupKey]);
    }
    return fallback;
  }

  function toggleGroupExpanded(groupKey, currentExpanded = null) {
    if (!groupKey) return;
    const groups = getExpandedGroups();
    groups[groupKey] = currentExpanded === null
      ? !isGroupExpanded(groupKey, getDefaultGroupExpanded(groupKey))
      : !currentExpanded;
    renderLoaderCard();
    syncAll();
    saveFormState();
  }

  function valueKey(value) {
    return value === undefined || value === null ? "" : String(value);
  }

  function getValueType(value) {
    if (typeof value === "number") return "number";
    if (typeof value === "boolean") return "boolean";
    return "string";
  }

  function decodeValueByType(value, valueType) {
    if (value === undefined || value === null || value === "") return "";
    if (valueType === "number") {
      const parsed = Number(value);
      return Number.isFinite(parsed) ? parsed : value;
    }
    if (valueType === "boolean") {
      return value === "true";
    }
    return value;
  }

  function valuesContain(values, targetValue) {
    return (Array.isArray(values) ? values : []).some((item) => valueKey(item) === valueKey(targetValue));
  }

  function normalizeSelectableValues(values) {
    return Array.isArray(values) ? [...values] : [];
  }

  async function handleLoadTalents() {
    if (state.sending) return;
    const mode = state.form.activeMode || MODES.FIND_DAREN;
    await ensureModeResources(mode);
    verifyModeBeforeLoad(mode);

    if (!state.hasMore && state.page > 1) {
      syncStatus("已经加载完毕，如需重新加载请点“清空重载”。");
      return;
    }

    state.loading = true;
    state.stopRequested = false;
    syncButtons();
    syncStatus(COPY.statusLoading);

    try {
      do {
        const currentPage = state.page;
        syncStatus(`正在加载第 ${currentPage} 页达人…`);
        const response = await loadTalentPageByMode(mode, currentPage, currentPage === 1);
        addTalents(response.list);
        state.total = response.total || state.total;
        state.hasMore = Boolean(response.hasMore && response.list.length > 0 && currentPage < MAX_LOAD_PAGE);
        state.page += 1;
        renderTalentTable();
        renderFilteredTable();
        syncAll();

        if (!state.hasMore || state.stopRequested) break;
        await delay(LOAD_PAGE_DELAY_MS);
      } while (state.page <= MAX_LOAD_PAGE);

      if (state.stopRequested) {
        syncStatus(COPY.statusStopped);
      } else if (!state.talents.size) {
        syncStatus(COPY.statusNoTargets);
      } else if (!state.hasMore) {
        syncStatus(`加载完成：可邀约 ${state.talents.size} 位，已过滤 ${state.filtered.size} 位。`);
      } else {
        syncStatus(`已加载 ${state.talents.size} 位，可继续加载。`);
      }
    } finally {
      state.loading = false;
      state.stopRequested = false;
      syncButtons();
    }
  }

  function verifyModeBeforeLoad(mode) {
    if (mode === MODES.SIMILAR_KOL) {
      const form = getModeForm(mode);
      if (!String(form.query || "").trim()) {
        throw new Error("请先选择一个达人后再加载。");
      }
    }

    if (mode === MODES.PRD_2_KOL) {
      const form = getModeForm(mode);
      if (!String(form.pid || "").trim()) {
        throw new Error("请先选择一个商品后再加载。");
      }
    }

    if (mode === MODES.REC_LIST) {
      const form = getModeForm(mode);
      if (!Array.isArray(form.author_type) || !form.author_type.length) {
        throw new Error("请先选择达人类型。");
      }
      if (!Array.isArray(form.target_crowd) || !form.target_crowd.length) {
        throw new Error("请先选择目标人群。");
      }
      if (!Array.isArray(form.matching_method) || !form.matching_method.length) {
        throw new Error("请先选择匹配方式。");
      }
    }
  }

  async function loadTalentPageByMode(mode, page, refresh) {
    if (mode === MODES.FIND_DAREN) {
      const form = getModeForm(mode);
      const payload = buildTalentListPayload({
        page,
        refresh,
        query: String(form.query || "").trim(),
        type: Number(form.type || 1),
        search_id: "",
        sort_field: form.sort_field === "" ? undefined : Number(form.sort_field),
        sort_type: form.sort_type === "" ? undefined : Number(form.sort_type)
      }, form.filters);
      const data = await douDianRequest("POST", API.searchAuthor, payload);
      return normalizeListResponse(data);
    }

    if (mode === MODES.SIMILAR_KOL) {
      const form = getModeForm(mode);
      const data = await douDianRequest("POST", API.similarList, buildTalentListPayload({
        page,
        refresh,
        author_id: String(form.query || "").trim(),
        req_source: Number(form.req_source || 1)
      }, form.filters));
      return {
        total: Number(data?.total || 0),
        list: Array.isArray(data?.author_list) ? data.author_list.map((item) => item?.author_data || item).filter(Boolean) : [],
        hasMore: Boolean(data?.has_more)
      };
    }

    if (mode === MODES.PRD_2_KOL) {
      const form = getModeForm(mode);
      const data = await douDianRequest("POST", API.productList, buildTalentListPayload({
        page,
        pid: String(form.pid || "").trim(),
        loadmore: !refresh
      }, form.filters));
      return {
        total: Number(data?.total || 0),
        list: Array.isArray(data?.author_list) ? data.author_list.map((item) => item?.author_data || item).filter(Boolean) : [],
        hasMore: Boolean(data?.has_more)
      };
    }

    if (mode === MODES.REC_LIST) {
      const form = getModeForm(mode);
      const data = await douDianRequest("POST", API.recListSearch, {
        page,
        page_size: 20,
        filters: cloneJson(coerceRecFiltersForRequest(form))
      });
      return {
        total: Number(data?.total || 0),
        list: Array.isArray(data?.author_list) ? data.author_list : [],
        hasMore: Boolean(data?.has_more)
      };
    }

    throw new Error("错误的达人加载模式。");
  }

  function buildTalentListPayload(base, filters) {
    const payload = cleanObject(base || {});
    const flatFilters = buildFlatPublicFilterParams(filters);
    Object.entries(flatFilters).forEach(([key, value]) => {
      payload[key] = value;
    });
    return cleanObject(payload);
  }

  function buildFlatPublicFilterParams(filters) {
    const source = cleanObject(cloneJson(coercePublicFiltersForRequest(filters)));
    const result = {};
    Object.entries(source).forEach(([key, value]) => {
      if (value === undefined || value === null || value === "") return;
      if (Array.isArray(value) && value.length === 0) return;
      if (value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0) return;
      result[key] = value;
    });
    return result;
  }

  function addTalents(list) {
    for (const raw of list || []) {
      const talent = normalizeTalent(raw);
      if (!talent.uid) continue;
      if (state.talents.has(talent.uid) || state.filtered.has(talent.uid)) continue;

      if (talent.imStatus === 1) {
        state.talents.set(talent.uid, talent);
        state.selected.add(talent.uid);
      } else {
        state.filtered.set(talent.uid, {
          uid: talent.uid,
          nickname: talent.nickname,
          reason: talent.reason || "当前达人不可邀约"
        });
      }
    }
  }

  async function searchSimilarCandidates() {
    const form = getModeForm(MODES.SIMILAR_KOL);
    const query = String(form.search_text || "").trim();
    if (!query) throw new Error("请输入达人昵称或抖音号。");
    syncStatus("正在查询相似达人候选…");
    const data = await douDianRequest("GET", API.similarSearchSuggest, {
      query,
      search_id: state.similarSearchId || ""
    });
    state.similarSearchId = String(data?.search_id || state.similarSearchId || "");
    state.similarSearchResults = normalizeSimilarSearchList(data?.sugList || []);
    renderLoaderCard();
    syncStatus(`已找到 ${state.similarSearchResults.length} 个达人候选。`);
  }

  async function searchProductCandidates() {
    const form = getModeForm(MODES.PRD_2_KOL);
    const query = String(form.search_text || "").trim();
    if (!query) throw new Error("请输入商品名称或商品 ID。");
    syncStatus("正在查询商品候选…");
    const data = await douDianRequest("GET", API.productSearchSuggest, { query });
    state.productSearchResults = normalizeProductList(data).map(normalizeProductCandidate).filter((item) => item.product_id);
    renderLoaderCard();
    syncStatus(`已找到 ${state.productSearchResults.length} 个商品候选。`);
  }

  function selectSimilarCandidate(index, source) {
    const sourceList = source === "suggest" ? state.similarSuggestList : state.similarSearchResults;
    const item = sourceList[index];
    if (!item) return;
    const form = getModeForm(MODES.SIMILAR_KOL);
    form.query = String(item.author_id || item.uid || "").trim();
    form.author_name = String(item.nickname || "").trim();
    form.search_text = form.author_name;
    form.req_source = 1;
    state.similarSearchResults = [];
    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  function selectProductCandidate(index, source) {
    const sourceList = source === "suggest" ? state.productSuggestList : state.productSearchResults;
    const item = sourceList[index];
    if (!item) return;
    const form = getModeForm(MODES.PRD_2_KOL);
    form.pid = String(item.product_id || item.id || "").trim();
    form.product_name = String(item.product_name || item.title || "").trim();
    form.search_text = form.product_name || form.pid;
    state.productSearchResults = [];
    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  async function loadStoreProducts(reset) {
    if (state.storeProductsLoading) return;
    state.storeProductsLoading = true;
    renderSendCard();

    try {
      const page = reset ? 1 : state.storeProductPage;
      const query = String(state.form.storeProductQuery || "").trim();
      const nextList = await requestPromotionProducts(page, query);
      state.storeProducts = reset ? nextList : mergeProducts(state.storeProducts, nextList);
      state.storeProductPage = page + 1;
      state.storeProductHasMore = nextList.length >= STORE_PRODUCT_PAGE_SIZE;
      renderSendCard();
    } finally {
      state.storeProductsLoading = false;
      renderSendCard();
    }
  }

  async function requestPromotionProducts(page, query) {
    const cleanQuery = String(query || "").trim();
    const attempts = cleanQuery
      ? [
          { page, query: cleanQuery, pageSize: STORE_PRODUCT_PAGE_SIZE },
          { page, page_size: STORE_PRODUCT_PAGE_SIZE, query: cleanQuery }
        ]
      : [
          { page, pageSize: STORE_PRODUCT_PAGE_SIZE },
          { page, page_size: STORE_PRODUCT_PAGE_SIZE }
        ];

    let lastError = null;
    let hadSuccess = false;
    let lastList = [];
    for (const params of attempts) {
      try {
        const data = await douDianRequest("GET", API.promotionList, cleanObject(params));
        const list = normalizeProductList(data).map(normalizeProductCandidate).filter((item) => item.product_id);
        hadSuccess = true;
        if (list.length) return list;
        lastList = list;
      } catch (error) {
        lastError = error;
      }
    }
    if (lastError && !hadSuccess) throw lastError;
    return lastList;
  }

  function toggleSelectedProduct(productId) {
    const selected = state.form.selectedProducts || [];
    const index = selected.findIndex((item) => String(item.product_id) === String(productId));
    if (index >= 0) {
      selected.splice(index, 1);
      renderSendCard();
      saveFormState();
      return;
    }

    if (selected.length >= MAX_INVITE_PRODUCTS) {
      toast(`推荐商品最多选择 ${MAX_INVITE_PRODUCTS} 个。`);
      return;
    }

    const source = state.storeProducts.find((item) => String(item.product_id) === String(productId));
    if (!source) return;
    selected.push({
      ...normalizeProductCandidate(source),
      author_sample_status: Number(source.author_sample_status ?? 1),
      customCommissionRatio: String(source.customCommissionRatio || "")
    });
    renderSendCard();
    saveFormState();
  }

  function removeSelectedProduct(productId) {
    const list = state.form.selectedProducts || [];
    const next = list.filter((item) => String(item.product_id) !== String(productId));
    state.form.selectedProducts = next;
    renderSendCard();
    saveFormState();
  }

  function updateSelectedProductField(productId, key, value, rerender = true) {
    const item = (state.form.selectedProducts || []).find((product) => String(product.product_id) === String(productId));
    if (!item) return;
    item[key] = value;
    if (rerender) renderSendCard();
    saveFormState();
  }

  function toggleInviteRight(value, checked, rerender = true) {
    const rights = Array.isArray(state.form.rights) ? state.form.rights : [];
    if (checked) {
      if (!rights.includes(value)) rights.push(value);
    } else {
      const index = rights.indexOf(value);
      if (index >= 0) rights.splice(index, 1);
    }
    if (rerender) renderSendCard();
    saveFormState();
  }

  function togglePublicFilter(mode, field, value, kind) {
    const form = getModeForm(mode);
    if (!form || !form.filters) return;
    const current = normalizeSelectableValues(form.filters[field]);
    const next = [...current];

    if (kind === "all") {
      form.filters[field] = [];
    } else if (kind === "single") {
      form.filters[field] = valuesContain(current, value) ? [] : [value];
    } else {
      const index = next.findIndex((item) => valueKey(item) === valueKey(value));
      if (index >= 0) next.splice(index, 1);
      else next.push(value);
      form.filters[field] = next;
    }

    if (field === PUBLIC_FILTER_FIELDS.contentType && !Array.isArray(form.filters[field])) {
      form.filters[field] = [];
    }

    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  function setPublicFilterSelect(mode, field, rawValue, valueType) {
    const form = getModeForm(mode);
    if (!form || !form.filters || !field) return;
    form.filters[field] = rawValue === "" || rawValue === undefined || rawValue === null
      ? []
      : [decodeValueByType(rawValue, valueType)];
    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  function updateCascadeFilter(mode, headerKey, level, rawValue) {
    const form = getModeForm(mode);
    if (!form) return;
    const item = findPublicHeaderItem(headerKey);
    if (!item) return;

    const pathMap = normalizePlainObject(form.cascadePaths);
    const currentPath = Array.isArray(pathMap[headerKey]) ? pathMap[headerKey] : [];
    const nextPath = currentPath.slice(0, level);
    if (rawValue !== "" && rawValue !== undefined && rawValue !== null) nextPath.push(rawValue);
    pathMap[headerKey] = nextPath;
    form.cascadePaths = pathMap;

    applyCascadeToFilters(form, item, nextPath);
    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  function clearCascadeFilter(mode, headerKey) {
    const form = getModeForm(mode);
    if (!form) return;
    const item = findPublicHeaderItem(headerKey);
    if (!item) return;
    form.cascadePaths = normalizePlainObject(form.cascadePaths);
    form.cascadePaths[headerKey] = [];
    applyCascadeToFilters(form, item, []);
    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  function applyCascadeToFilters(form, item, path) {
    if (!form.filters) form.filters = {};
    const field = String(item.field_name || "").trim();
    if (!field) return;

    if (field === PUBLIC_FILTER_FIELDS.mainCateNew) {
      form.filters[PUBLIC_FILTER_FIELDS.mainCateNew] = [];
      form.filters[PUBLIC_FILTER_FIELDS.cateFirst] = [];
      form.filters[PUBLIC_FILTER_FIELDS.cateSecond] = [];
      form.filters[PUBLIC_FILTER_FIELDS.cateThird] = [];
      if (!path.length) return;
      if (item.value !== undefined && item.value !== null && item.value !== "") {
        form.filters[PUBLIC_FILTER_FIELDS.mainCateNew] = [String(item.value)];
      }
      if (path[0] !== undefined && path[0] !== null && path[0] !== "") form.filters[PUBLIC_FILTER_FIELDS.cateFirst] = [String(path[0])];
      if (path[1] !== undefined && path[1] !== null && path[1] !== "") form.filters[PUBLIC_FILTER_FIELDS.cateSecond] = [String(path[1])];
      if (path[2] !== undefined && path[2] !== null && path[2] !== "") form.filters[PUBLIC_FILTER_FIELDS.cateThird] = [String(path[2])];
      return;
    }

    form.filters[field] = path.length ? [String(path[path.length - 1])] : [];
  }

  function toggleRecListFilter(field, value, kind) {
    const form = getModeForm(MODES.REC_LIST);
    if (!form || !Array.isArray(form[field])) return;
    const current = normalizeSelectableValues(form[field]);

    if (kind === "single") {
      form[field] = valuesContain(current, value) ? [] : [value];
    } else {
      const index = current.findIndex((item) => valueKey(item) === valueKey(value));
      if (index >= 0) current.splice(index, 1);
      else current.push(value);
      form[field] = current;
    }

    resetTalentState();
    renderLoaderCard();
    renderTalentTable();
    renderFilteredTable();
    syncAll();
    saveFormState();
  }

  async function handleSendInvites() {
    if (state.loading) return;

    const selectedTalents = Array.from(state.selected)
      .map((uid) => state.talents.get(uid))
      .filter(Boolean)
      .filter((talent) => talent.resultType !== "success");

    if (!selectedTalents.length) throw new Error("请先选择要发送邀约的达人。");
    if (!String(state.form.inviteText || "").trim()) throw new Error("请填写邀约信息。");

    const selectedProducts = normalizeSelectedProductList(state.form.selectedProducts || []);
    const fallbackProductIds = parseIdList(state.form.manualProductIdsText);
    if (!selectedProducts.length && !fallbackProductIds.length) {
      throw new Error("请先勾选推荐商品。");
    }

    selectedTalents.forEach((talent) => {
      talent.resultType = "";
      talent.resultText = "";
    });
    renderTalentTable();

    state.sending = true;
    state.stopRequested = false;
    syncButtons();
    syncStatus("正在读取抖店邀约卡片信息…");

    try {
      const cardInfo = await getInviteCardInfo();
      const cardVersion = Number(cardInfo?.invite_card_info?.card_version ?? cardInfo?.card_version ?? 0);
      state.cardVersion = cardVersion;
      if (![0, 1].includes(cardVersion)) {
        throw new Error("当前抖店邀约卡片版本暂不支持，请先在抖店页面手动邀约一位达人后再试。");
      }

      const products = selectedProducts.length
        ? selectedProducts
        : await loadProductsByIdList(fallbackProductIds);
      const hydratedProducts = await hydrateInviteProducts(products);

      const form = buildInviteForm(cardInfo, hydratedProducts, cardVersion);
      let batchSize = 10;
      let degraded = false;
      let completed = 0;

      while (selectedTalents.some((talent) => !talent.resultType) && !state.stopRequested) {
        const pending = selectedTalents.filter((talent) => !talent.resultType);
        const batch = pending.slice(0, batchSize);
        syncStatus(`正在发送 ${completed + 1}-${completed + batch.length}/${selectedTalents.length} 位达人…`);

        try {
          const useBatch = !degraded && batchSize > 1;
          const results = useBatch
            ? await sendBatch(batch, form, cardVersion)
            : await sendSingleBatch(batch, form, cardVersion);
          if (useBatch && shouldRetryBatchAsSingle(results)) {
            degraded = true;
            batchSize = 1;
            syncStatus("抖店批量接口参数不兼容，已自动切换为单个达人发送。");
            continue;
          }
          applySendResults(results);
          completed += results.length || batch.length;
          renderTalentTable();
          syncAll();
        } catch (error) {
          if (!degraded && shouldDowngrade(error) && !isParameterError(error)) {
            degraded = true;
            batchSize = 1;
            syncStatus(isParameterError(error) ? "抖店批量接口参数不兼容，已自动切换为单个达人发送。" : "抖店提示频繁或风控，已自动降级为单个达人发送。");
            continue;
          }
          applySendResults(batch.map((talent) => ({
            uid: talent.uid,
            type: "error",
            text: error?.message || "发送失败"
          })));
          completed += batch.length;
          renderTalentTable();
        }

        if (state.stopRequested) break;
        const remained = selectedTalents.some((talent) => !talent.resultType);
        if (remained) {
          await countdownWait(state.form.intervalSeconds, completed, selectedTalents.length);
        }
      }

      syncStatus(state.stopRequested ? COPY.statusStopped : COPY.statusSent);
    } finally {
      state.sending = false;
      state.stopRequested = false;
      syncButtons();
    }
  }

  async function getInviteCardInfo() {
    const data = await douDianRequest("GET", API.senderMsg, {
      card_type: 0,
      is_open_feed: true
    });

    const contact = data?.contact_info || {};
    let changed = false;
    if (!state.form.phone && contact.phone) {
      state.form.phone = String(contact.phone || "");
      changed = true;
    }
    if (!state.form.wechat && contact.wechat) {
      state.form.wechat = String(contact.wechat || "");
      changed = true;
    }

    if (changed) {
      renderSendCard();
      await saveFormState();
    }

    return data;
  }

  async function loadProductsByIdList(productIds) {
    const products = [];
    for (const productId of productIds) {
      if (state.stopRequested) break;
      syncStatus(`正在读取商品 ${productId} 信息…`);
      const list = await requestPromotionProducts(1, productId).catch(() => []);
      const found = list.find((item) => String(item.product_id) === String(productId)) || list[0];
      products.push(found ? { ...found, product_id: String(found.product_id || productId) } : {
        product_id: String(productId),
        product_name: `商品 ${productId}`,
        author_sample_status: 1
      });
      await delay(120);
    }
    return products;
  }

  async function hydrateInviteProducts(products) {
    const normalized = normalizeSelectedProductList(products);
    const hydrated = [];
    for (const product of normalized) {
      if (state.stopRequested) break;
      const productId = String(product.product_id || "").trim();
      if (!productId) continue;
      syncStatus(`正在校验商品 ${productId} 发送参数…`);
      const list = await requestPromotionProducts(1, productId).catch(() => []);
      hydrated.push(mergeInviteProduct(product, findProductById(list, productId)));
      await delay(100);
    }
    if (!hydrated.length) throw new Error("未读取到可发送的推荐商品。");
    return hydrated;
  }

  function findProductById(list, productId) {
    const items = Array.isArray(list) ? list : [];
    return items.find((item) => String(item.product_id) === String(productId)) || items[0] || null;
  }

  function mergeInviteProduct(selected, fetched) {
    const base = normalizeProductCandidate(fetched || selected);
    const selectedStatus = firstNonEmpty(
      selected?.author_sample_status,
      selected?.sample?.author_sample_status,
      selected?.sample?.apply_style,
      ""
    );
    return ensureInviteProductDefaults({
      ...base,
      product_id: String(base.product_id || selected?.product_id || selected?.id || "").trim(),
      customCommissionRatio: String(firstNonEmpty(selected?.customCommissionRatio, "")),
      author_sample_status: selectedStatus !== "" ? selectedStatus : base.author_sample_status
    });
  }

  function buildInviteForm(cardInfo, products, cardVersion) {
    const contactInfo = {
      ...(cardInfo?.contact_info || {}),
      ...(state.form.phone ? { phone: state.form.phone.trim() } : {}),
      ...(state.form.wechat ? { wechat: state.form.wechat.trim() } : {})
    };

    const rights = normalizeRights(state.form.rights);
    const categories = normalizeInviteCategories(cardInfo);

    return {
      content: String(state.form.inviteText || "").trim(),
      contact_info: contactInfo,
      rights,
      categories,
      is_open_feed: true,
      card_version: cardVersion,
      goods: products.map((product) => normalizeProductSetting(product))
    };
  }

  function normalizeProductSetting(product) {
    const customRatio = Number(product?.customCommissionRatio || 0);
    const globalRatio = Number(state.form.commissionRatio || 0);
    const ratio = customRatio > 0 ? customRatio : globalRatio;

    let orientDetail;
    if (hasOrientOverride(product?.setOrientCosRatioDetail)) {
      const overrideSuggest = normalizeFiniteNumber(firstNonEmpty(
        product.setOrientCosRatioDetail.suggest_orient_kol_cos_ratio,
        product.setOrientCosRatioDetail.orient_kol_cos_ratio,
        ratio
      ), 0);
      const overrideRatio = normalizeFiniteNumber(firstNonEmpty(
        product.setOrientCosRatioDetail.orient_kol_cos_ratio,
        overrideSuggest
      ), overrideSuggest);
      orientDetail = {
        orient_kol_cos_ratio: overrideRatio,
        suggest_orient_kol_cos_ratio: overrideSuggest,
        valid_time: String(product.setOrientCosRatioDetail.valid_time || "3000-01-01 00:00:00")
      };
      if (product.setOrientCosRatioDetail.time_radio === "end") {
        orientDetail.time_radio = "end";
      }
    } else if (ratio > 0) {
      orientDetail = {
        orient_kol_cos_ratio: ratio,
        suggest_orient_kol_cos_ratio: ratio,
        valid_time: "3000-01-01 00:00:00"
      };
    } else {
      orientDetail = normalizeDefaultOrientDetail(product);
    }

    return {
      product_id: String(product.product_id || product.id || "").trim(),
      author_sample_status: normalizeAuthorSampleStatus(product),
      orient_cos_ratio_detail: orientDetail
    };
  }

  function ensureInviteProductDefaults(product) {
    const normalized = normalizeProductCandidate(product);
    const orientDetail = normalizeDefaultOrientDetail(product);
    return {
      ...normalized,
      product_id: String(normalized.product_id || product?.product_id || product?.id || "").trim(),
      author_sample_status: normalizeAuthorSampleStatus(product),
      orient_cos_ratio_detail: cloneJson(orientDetail),
      cos_ratio_range: cloneJson(orientDetail.cos_ratio_range || { low: 0, high: 70 }),
      suggest_orient_kol_cos_ratio: orientDetail.suggest_orient_kol_cos_ratio,
      customCommissionRatio: String(firstNonEmpty(product?.customCommissionRatio, normalized.customCommissionRatio, ""))
    };
  }

  function normalizeDefaultOrientDetail(product) {
    const detail = product?.orient_cos_ratio_detail || {};
    const range = detail.cos_ratio_range || product?.cos_ratio_range || {};
    const low = normalizeFiniteNumber(firstNonEmpty(range.low, range.min, range.min_value, 0), 0);
    const high = normalizeFiniteNumber(firstNonEmpty(range.high, range.max, range.max_value, 70), 70);
    const suggest = normalizeFiniteNumber(firstNonEmpty(
      detail.suggest_orient_kol_cos_ratio,
      product?.suggest_orient_kol_cos_ratio,
      product?.cos_ratio,
      low
    ), low);
    return {
      cos_ratio_range: {
        low,
        high: high < low ? low : high
      },
      suggest_orient_kol_cos_ratio: suggest
    };
  }

  function normalizeFiniteNumber(value, fallback) {
    const number = Number(value);
    return Number.isFinite(number) ? number : fallback;
  }

  function hasOrientOverride(detail) {
    if (!detail || typeof detail !== "object") return false;
    return detail.orient_kol_cos_ratio !== undefined
      || detail.suggest_orient_kol_cos_ratio !== undefined
      || detail.valid_time !== undefined;
  }

  function normalizeInviteCategories(cardInfo) {
    const manual = parseIdList(state.form.legacyCategoryIdsText).map((id) => ({ id }));
    if (manual.length) return manual;

    const inviteCard = cardInfo?.invite_card_info || cardInfo?.invite_card || {};
    const rawCategories = firstNonEmpty(
      inviteCard.categories,
      inviteCard.category_ids,
      inviteCard.category_list,
      cardInfo?.categories,
      cardInfo?.category_ids,
      []
    );
    return normalizeCategoryList(rawCategories);
  }

  function normalizeCategoryList(value) {
    const list = Array.isArray(value) ? value : parseIdList(value);
    return list
      .map((item) => {
        const id = firstNonEmpty(item?.id, item?.category_id, item?.cate_id, item);
        return String(id || "").trim();
      })
      .filter(Boolean)
      .map((id) => ({ id }));
  }

  function normalizeAuthorSampleStatus(product) {
    const status = Number(firstNonEmpty(
      product?.author_sample_status,
      product?.sample?.author_sample_status,
      product?.sample?.apply_style,
      1
    ));
    return status === 3 ? 1 : (status || 1);
  }

  function buildBatchPayload(talents, form, cardVersion) {
    const inviteCard = {
      content: cardVersion === 1 ? "from buyin" : form.content,
      rights: form.rights.map((right) => ({ right })),
      product_ids: form.goods.map((goods) => goods.product_id),
      product_setting: form.goods.map((goods) => cleanObject(goods))
    };

    if (cardVersion === 1) {
      inviteCard.is_open_feed = true;
      inviteCard.card_version = 1;
      inviteCard.categories = form.categories;
    }

    return cleanObject({
      event_param: buildEventParam(),
      receiver_messages: talents.map((talent) => ({
        receiver: {
          account_id: getTalentAccountId(talent),
          account_type: 24
        }
      })),
      message_content: {
        contact_info: cleanObject(form.contact_info),
        invite_card: cleanObject(inviteCard)
      },
      source: 5
    });
  }

  function buildSinglePayload(talent, form, cardVersion) {
    const inviteCard = {
      content: cardVersion === 1 ? "from buyin" : form.content,
      rights: form.rights.map((right) => ({ right })),
      product_ids: form.goods.map((goods) => goods.product_id),
      product_setting: form.goods.map((goods) => cleanObject(goods))
    };

    if (cardVersion === 1) {
      inviteCard.is_open_feed = true;
      inviteCard.card_version = 1;
      inviteCard.categories = form.categories;
    }

    return cleanObject({
      account_id: getTalentAccountId(talent),
      account_type: 1,
      contact_info: cleanObject(form.contact_info),
      invite_card: cleanObject(inviteCard),
      event_param: buildEventParam()
    });
  }

  function getTalentAccountId(talent) {
    return firstTalentId(
      talent?.accountId,
      talent?.uid,
      talent?.raw?.author_base?.uid,
      talent?.raw?.uid,
      talent?.raw?.author_id_str,
      talent?.raw?.author_base?.author_id_str,
      talent?.raw?.author_id,
      talent?.raw?.author_base?.author_id
    );
  }

  async function sendBatch(talents, form, cardVersion) {
    const payload = buildBatchPayload(talents, form, cardVersion);
    debugInviteLog("batch payload", summarizeInvitePayload(payload));
    const raw = await douDianRequest("POST", API.batchSend, payload, { returnAll: true });
    debugInviteLog("batch response", summarizeInviteResponse(raw));
    const data = raw?.data || raw?.body?.data || raw;
    const failedList = Array.isArray(data?.biz_failed_list) ? data.biz_failed_list : [];

    if (data?.biz_failed_count && failedList.length) {
      return talents.map((talent) => {
        const failed = failedList.find((item) => {
          const accountId = item?.msg_info?.receiver?.account_id ?? item?.receiver?.account_id;
          return String(accountId) === String(getTalentAccountId(talent));
        });
        return failed
          ? { uid: talent.uid, type: "error", text: failed.hover || failed.msg || "发送失败" }
          : { uid: talent.uid, type: "success", text: "成功" };
      });
    }

    return talents.map((talent) => ({ uid: talent.uid, type: "success", text: "成功" }));
  }

  async function sendSingleBatch(talents, form, cardVersion) {
    const results = [];
    for (const talent of talents) {
      if (state.stopRequested) break;
      try {
        const batchResults = await sendBatch([talent], form, cardVersion);
        results.push(batchResults[0] || { uid: talent.uid, type: "success", text: "success" });
      } catch (error) {
        results.push({ uid: talent.uid, type: "error", text: error?.message || "发送失败" });
      }
    }
    return results;
  }

  function debugInviteLog(label, value) {
    const entry = {
      source: "daren-invite",
      event: label,
      pageUrl: location.href,
      payload: value
    };
    try {
      chrome.runtime.sendMessage({ type: "ADMIN_DEBUG_LOG", entry }).catch(() => {});
    } catch (_) {
      // Optional admin debug sink.
    }
    try {
      if (localStorage.getItem("mmwInviteDebug") !== "1") return;
      console.log(`[MMW_INVITE] ${label}`, cloneJson(value));
    } catch (_) {
      // Best-effort debug hook only.
    }
  }

  function summarizeInvitePayload(payload) {
    const inviteCard = payload?.message_content?.invite_card || payload?.invite_card || {};
    return {
      receiver_count: Array.isArray(payload?.receiver_messages) ? payload.receiver_messages.length : 1,
      receivers: Array.isArray(payload?.receiver_messages)
        ? payload.receiver_messages.map((item) => item?.receiver)
        : [{ account_id: payload?.account_id, account_type: payload?.account_type }],
      product_ids: inviteCard.product_ids,
      product_setting: inviteCard.product_setting,
      categories: inviteCard.categories,
      rights: inviteCard.rights,
      card_version: inviteCard.card_version,
      source: payload?.source
    };
  }

  function summarizeInviteResponse(raw) {
    const data = raw?.data || raw?.body?.data || raw;
    return {
      code: raw?.code ?? raw?.err_no ?? raw?.status_code,
      msg: raw?.msg || raw?.message || raw?.err_msg || raw?.status_msg,
      biz_failed_count: data?.biz_failed_count,
      biz_failed_list: Array.isArray(data?.biz_failed_list)
        ? data.biz_failed_list.map((item) => ({
          account_id: item?.msg_info?.receiver?.account_id ?? item?.receiver?.account_id,
          msg: item?.msg,
          hover: item?.hover
        }))
        : []
    };
  }

  function summarizeXRequestResult(result) {
    if (!result || typeof result !== "object") return result;
    const data = result?.data || result?.body?.data || result;
    const list = firstArrayValue(data, ["list", "authors", "author_list", "products", "data"]);
    return {
      code: result?.code ?? result?.err_no ?? result?.status_code,
      msg: result?.msg || result?.message || result?.err_msg || result?.status_msg,
      keys: Object.keys(data || {}).slice(0, 40),
      total: data?.total ?? data?.count ?? data?.total_count,
      list_count: Array.isArray(list) ? list.length : undefined,
      list_sample: Array.isArray(list) ? list.slice(0, 3) : undefined,
      biz_failed_count: data?.biz_failed_count,
      biz_failed_list: Array.isArray(data?.biz_failed_list)
        ? data.biz_failed_list.map((item) => ({
          account_id: item?.msg_info?.receiver?.account_id ?? item?.receiver?.account_id,
          msg: item?.msg,
          hover: item?.hover
        }))
        : undefined
    };
  }

  function firstArrayValue(source, keys) {
    if (!source || typeof source !== "object") return null;
    for (const key of keys) {
      if (Array.isArray(source[key])) return source[key];
    }
    return null;
  }

  function applySendResults(results) {
    for (const result of results || []) {
      const talent = state.talents.get(String(result.uid));
      if (!talent) continue;
      talent.resultType = result.type;
      talent.resultText = result.text || (result.type === "success" ? "成功" : "失败");
      if (result.type === "success") state.selected.delete(talent.uid);
    }
  }

  async function countdownWait(seconds, completed, total) {
    const count = normalizeInterval(seconds);
    for (let left = count; left > 0; left -= 1) {
      if (state.stopRequested) break;
      syncStatus(`处理中（${completed}/${total}）… ${left} 秒后继续`);
      await delay(1000);
    }
  }

  async function douDianRequest(method, url, data = null, options = {}) {
    const raw = await xPageRequest(method, url, data, options.timeoutMs || 20000);
    if (typeof raw === "string") throw new Error(normalizeDouDianMessage(raw));
    if (!raw || typeof raw !== "object") throw new Error("抖店接口返回为空。");

    const code = raw.code ?? raw.err_no ?? raw.status_code;
    const ok = code === undefined || code === 0 || code === "0";
    if (!ok) {
      throw new Error(normalizeDouDianMessage(raw.msg || raw.message || raw.err_msg || raw.status_msg || `抖店接口失败：${code}`));
    }

    if (options.returnAll) return raw;
    return raw.data ?? raw.body?.data ?? raw;
  }

  function xPageRequest(method, rawUrl, data, timeoutMs) {
    const uuid = `mmw_daren_${Date.now()}_${state.requestSeq++}`;
    const url = buildRequestUrl(method, rawUrl, data);
    const requestMethod = String(method || "GET").toUpperCase();
    const body = requestMethod === "GET" ? null : data;
    const requestData = {
      method: requestMethod,
      url,
      data: body ? cloneJson(body) : null,
      uuid
    };
    debugInviteLog("xrequest request", requestData);

    return new Promise((resolve, reject) => {
      const timer = window.setTimeout(() => {
        state.requestWaiters.delete(uuid);
        reject(new Error(COPY.requestTimeout));
      }, timeoutMs);

      state.requestWaiters.set(uuid, { resolve, reject, timer });

      try {
        window.postMessage({
          action: "request",
          data: requestData
        }, "*");
      } catch (error) {
        window.clearTimeout(timer);
        state.requestWaiters.delete(uuid);
        reject(error);
      }
    });
  }

  function buildRequestUrl(method, rawUrl, data) {
    const upper = String(method || "GET").toUpperCase();
    if (upper !== "GET" || !data || typeof data !== "object") return rawUrl;
    const params = new URLSearchParams();
    for (const [key, value] of Object.entries(data)) {
      if (value === undefined || value === null || value === "") continue;
      if (Array.isArray(value)) {
        if (!value.length) continue;
        params.set(key, value.join(","));
        continue;
      }
      params.set(key, String(value));
    }
    const query = params.toString();
    if (!query) return rawUrl;
    return `${rawUrl}${rawUrl.includes("?") ? "&" : "?"}${query}`;
  }

  function renderLoaderCard() {
    const node = document.getElementById(IDS.loaderCard);
    if (!node) return;
    node.innerHTML = `
      <section class="mmwInviteCard mmwInviteControlCard mmwInviteControlCard--hsq">
        <div class="mmwInviteModeTabs mmwInviteModeTabs--hsq">
          ${Object.entries(MODE_LABELS).map(([mode, label]) => `
            <button
              type="button"
              class="mmwInviteModeTab ${state.form.activeMode === mode ? "is-active" : ""}"
              data-action="switchMode"
              data-mode="${mode}"
            >${escapeHtml(label)}</button>
          `).join("")}
        </div>
        <div class="mmwInviteModePanel">
          ${renderModePanel()}
        </div>
        <div class="mmwInviteControlFooter mmwInviteControlFooter--hsq">
          <button id="${IDS.resetButton}" class="mmwInviteResetCenterButton" type="button" data-action="resetTalents">重置</button>
          <div class="mmwInviteDealBar">
            <div class="mmwInviteStatsLine">
              <span id="${IDS.count}">已加载 ${state.talents.size} 位达人${state.total ? ` / 抖店共 ${state.total} 位` : ""}</span>
              <span id="${IDS.selected}">已选择 ${state.selected.size} 位</span>
              <span id="${IDS.filtered}">已过滤 ${state.filtered.size} 位不可邀约达人</span>
            </div>
            <div class="mmwInviteBottomActions">
              <label class="mmwInviteIntervalField">
                <span>邀约间隔</span>
                <select id="${IDS.interval}" class="mmwInviteInput mmwInviteIntervalSelect">
                  ${INTERVAL_OPTIONS.map((item) => `<option value="${item}" ${Number(state.form.intervalSeconds || 5) === item ? "selected" : ""}>${item} 秒</option>`).join("")}
                </select>
              </label>
              <button id="${IDS.loadButton}" class="mmwInviteActionButton mmwInviteLoadButton" type="button" data-action="loadTalents">${state.loading ? COPY.loadStop : state.page > 1 && state.hasMore ? COPY.loadContinue : COPY.loadStart}</button>
              <button id="${IDS.openSendButton}" class="mmwInviteActionButton mmwInviteInviteButton" type="button" data-action="openSendDialog">${COPY.send}</button>
            </div>
          </div>
        </div>
      </section>
    `;
    syncButtons();
    syncCounts();
  }

  function renderModePanel() {
    const mode = state.form.activeMode || MODES.FIND_DAREN;
    if (mode === MODES.FIND_DAREN) return renderFindDarenPanel();
    if (mode === MODES.SIMILAR_KOL) return renderSimilarPanel();
    if (mode === MODES.PRD_2_KOL) return renderProductModePanel();
    if (mode === MODES.REC_LIST) return renderRecListPanel();
    return "";
  }

  function renderFindDarenPanel() {
    const form = getModeForm(MODES.FIND_DAREN);
    const sortOptions = SORT_FIELDS[Number(form.type || 1)] || SORT_FIELDS[1] || [];
    return `
      <div class="mmwInviteModeBody">
        <div class="mmwInviteSearchHeader">
          <div class="mmwInviteTagBar mmwInviteContentTypeTabs">
            ${CONTENT_TYPES.map((item) => `
              <button
                type="button"
                class="mmwInviteContentTypeTab ${Number(form.type || 1) === item.value ? "is-active" : ""}"
                data-action="setContentType"
                data-value="${item.value}"
              >${escapeHtml(item.label)}</button>
            `).join("")}
          </div>
          <div class="mmwInviteKeywordSearch">
            <input id="${IDS.findKeyword}" class="mmwInviteInput" value="${escapeHtml(form.query || "")}" placeholder="搜达人昵称、抖音号、带货品牌、主推类目">
            <button type="button" class="mmwInviteSubAction mmwInviteSearchButton" data-action="loadTalents">搜索</button>
          </div>
        </div>
        ${renderPublicFilterSchema(MODES.FIND_DAREN)}
        ${renderSortBar(form, sortOptions)}
      </div>
    `;
  }

  function renderSortBar(form, sortOptions) {
    return `
      <div class="mmwInviteSortBar">
        <label class="mmwInviteField">
          <span>排序字段</span>
          <select id="${IDS.sortField}" class="mmwInviteInput">
            <option value="">不排序</option>
            ${sortOptions.map((item) => `<option value="${item.value}" ${String(form.sort_field) === String(item.value) ? "selected" : ""}>${escapeHtml(item.label)}</option>`).join("")}
          </select>
        </label>
        <label class="mmwInviteField">
          <span>排序方式</span>
          <select id="${IDS.sortType}" class="mmwInviteInput">
            <option value="">默认</option>
            ${SORT_TYPES.map((item) => `<option value="${item.value}" ${String(form.sort_type) === String(item.value) ? "selected" : ""}>${escapeHtml(item.label)}</option>`).join("")}
          </select>
        </label>
      </div>
    `;
  }

  function renderTalentColumnSettings() {
    const columns = normalizeTalentColumns(state.form.talentColumns);
    return `
      <div class="mmwInviteColumnSettings">
        <button
          type="button"
          class="mmwInviteTableTool mmwInviteColumnSettingsButton"
          data-action="toggleColumnSettings"
          aria-expanded="false"
          aria-controls="${IDS.columnSettings}"
        >列设置</button>
        <div id="${IDS.columnSettings}" class="mmwInviteColumnSettingsPanel" hidden>
          <div class="mmwInviteColumnSettingsHeader">
            <span>表格列设置</span>
            <button type="button" class="mmwInviteTinyTextButton" data-action="resetTalentColumns">恢复默认</button>
          </div>
          <div class="mmwInviteColumnSettingsList">
            ${TALENT_TABLE_COLUMNS.map((column) => `
              <label class="mmwInviteColumnOption">
                <span>${escapeHtml(column.label)}</span>
                <input
                  type="checkbox"
                  data-action="toggleTalentColumn"
                  data-column-key="${escapeHtml(column.key)}"
                  ${columns[column.key] ? "checked" : ""}
                >
              </label>
            `).join("")}
          </div>
        </div>
      </div>
    `;
  }

  function toggleColumnSettings() {
    const panel = document.getElementById(IDS.columnSettings);
    const button = document.querySelector(".mmwInviteColumnSettingsButton");
    if (!panel) return;
    const nextOpen = panel.hasAttribute("hidden");
    panel.toggleAttribute("hidden", !nextOpen);
    panel.classList.toggle("is-open", nextOpen);
    button?.setAttribute("aria-expanded", String(nextOpen));
  }

  function setTalentColumnVisible(key, visible) {
    if (!TALENT_TABLE_COLUMNS.some((column) => column.key === key)) return;
    state.form.talentColumns = normalizeTalentColumns({
      ...state.form.talentColumns,
      [key]: Boolean(visible)
    });
    applyTalentColumnVisibility();
    saveFormState();
  }

  function syncTalentColumnSettings() {
    const columns = normalizeTalentColumns(state.form.talentColumns);
    document.querySelectorAll("[data-action='toggleTalentColumn']").forEach((node) => {
      if (!(node instanceof HTMLInputElement)) return;
      node.checked = Boolean(columns[node.dataset.columnKey]);
    });
  }

  function applyTalentColumnVisibility() {
    const table = document.querySelector(".mmwInviteTalentTable");
    if (!table) return;
    table.className = `mmwInviteTable mmwInviteTalentTable ${talentTableColumnClass()}`.trim();
  }

  function talentTableColumnClass() {
    const columns = normalizeTalentColumns(state.form.talentColumns);
    return TALENT_TABLE_COLUMNS
      .filter((column) => !columns[column.key])
      .map((column) => `is-hide-${column.key}`)
      .join(" ");
  }

  function renderSimilarPanel() {
    const form = getModeForm(MODES.SIMILAR_KOL);
    return `
      <div class="mmwInviteModeBody">
        <div class="mmwInviteSearchHeader mmwInviteSearchHeader--single">
          <div class="mmwInviteKeywordSearch">
            <input id="${IDS.similarKeyword}" class="mmwInviteInput" value="${escapeHtml(form.search_text || "")}" placeholder="请输入达人昵称、抖音号">
            <button type="button" class="mmwInviteSubAction mmwInviteSearchButton" data-action="searchSimilarCandidates">搜索</button>
          </div>
        </div>
        ${form.query ? `
          <div class="mmwInviteSelectedSeed">
            <span>当前搜索达人：</span>
            <strong>${escapeHtml(form.author_name || form.query)}</strong>
            <button type="button" class="mmwInviteTinyTextButton" data-action="clearSimilar">清除</button>
          </div>
        ` : `<div class="mmwInviteHint">搜索框输入内容后，先从候选中选中达人，再点击“开始加载”。</div>`}
        ${renderCandidateList("猜你想找", state.similarSuggestList, "selectSimilarCandidate", "suggest", "author")}
        ${renderCandidateList("达人候选", state.similarSearchResults, "selectSimilarCandidate", "search", "author")}
      </div>
    `;
  }

  function renderProductModePanel() {
    const form = getModeForm(MODES.PRD_2_KOL);
    return `
      <div class="mmwInviteModeBody">
        <div class="mmwInviteSearchHeader mmwInviteSearchHeader--single">
          <div class="mmwInviteKeywordSearch">
            <input id="${IDS.productKeyword}" class="mmwInviteInput" value="${escapeHtml(form.search_text || "")}" placeholder="输入本店铺中、推广中的商品名称或id号">
            <button type="button" class="mmwInviteSubAction mmwInviteSearchButton" data-action="searchProductCandidates">搜索</button>
          </div>
        </div>
        ${form.pid ? `
          <div class="mmwInviteSelectedSeed">
            <span>当前搜索商品：</span>
            <strong>${escapeHtml(form.product_name || form.pid)}</strong>
            <button type="button" class="mmwInviteTinyTextButton" data-action="clearProductSeed">清除</button>
          </div>
        ` : `<div class="mmwInviteHint">先从候选商品中选中一个商品，再点击“开始加载”。</div>`}
        ${renderCandidateList("猜你想找", state.productSuggestList, "selectProductCandidate", "suggest", "product")}
        ${renderCandidateList("商品候选", state.productSearchResults, "selectProductCandidate", "search", "product")}
      </div>
    `;
  }

  function renderRecListPanel() {
    if (state.recListLoading) {
      return `<div class="mmwInviteHintCard">正在加载人群包筛选参数…</div>`;
    }

    if (!state.recListSchema) {
      return `<div class="mmwInviteHintCard">还未拿到抖店人群包筛选参数，请稍后重试。</div>`;
    }

    const form = getModeForm(MODES.REC_LIST);
    const optionSections = Array.isArray(state.recListSchema?.option_headers_list?.[0]) ? state.recListSchema.option_headers_list[0] : [];
    const baseSections = Array.isArray(state.recListSchema?.base_headers) ? state.recListSchema.base_headers : [];

    return `
      <div class="mmwInviteModeBody">
        <div class="mmwInviteRecPanel">
          <div class="mmwInviteRecStep">
            <div class="mmwInviteRecStepTitle"><span>1</span>选择人群属性</div>
            <div class="mmwInviteRecRows">
              ${optionSections.map((section) => renderRecFilterRow(section, form, "single")).join("")}
            </div>
          </div>
          <div class="mmwInviteRecStep">
            <div class="mmwInviteRecStepTitle"><span>2</span>选择达人属性</div>
            <div class="mmwInviteRecRows">
              ${baseSections.map((section) => renderRecFilterRow(section, form, "multi")).join("")}
            </div>
          </div>
        </div>
      </div>
    `;
  }

  function renderRecFilterRow(section, form, kind) {
    const header = Array.isArray(section?.header) ? section.header.filter((item) => item?.value !== undefined) : [];
    if (!header.length) return "";
    return `
      <div class="mmwInviteRecRow">
        <div class="mmwInviteRecRowLabel">${escapeHtml(section.name || "")}</div>
        <div class="mmwInviteChipGroup">
          ${header.map((item) => {
            const values = Array.isArray(form[item.field_name]) ? form[item.field_name] : [];
            const active = valuesContain(values, item.value);
            return `
              <button
                type="button"
                class="mmwInviteChip ${active ? "is-active" : ""} ${item.invalid ? "is-disabled" : ""}"
                data-action="toggleRecFilter"
                data-field="${escapeHtml(item.field_name || "")}"
                data-value="${escapeHtml(String(item.value ?? ""))}"
                data-value-type="${getValueType(item.value)}"
                data-kind="${kind}"
                data-disabled="${item.invalid ? "1" : "0"}"
              >${escapeHtml(item.name || "")}</button>
            `;
          }).join("")}
        </div>
      </div>
    `;
  }

  function renderFilterGroupShell({ title, groupKey, bodyHtml, defaultExpanded = false, bodyClassName = "", foldable = true }) {
    const expanded = isGroupExpanded(groupKey, defaultExpanded);
    return `
      <div class="mmwInviteFilterGroup mmwInviteFilterGroup--hsq ${bodyClassName} ${foldable ? "is-foldable" : "is-static"} ${expanded ? "is-expanded" : "is-collapsed"}">
        <div class="mmwInviteFilterGroupTitle">${escapeHtml(title)}</div>
        <div class="mmwInviteFilterGroupBody">${bodyHtml}</div>
        ${foldable ? `<button
          type="button"
          class="mmwInviteFilterGroupToggle"
          data-action="toggleGroupExpand"
          data-group-key="${escapeHtml(groupKey)}"
          aria-expanded="${expanded ? "true" : "false"}"
        >${expanded ? "收起⌃" : "更多⌄"}</button>` : ""}
      </div>
    `;
  }

  function renderPublicFilterSchema(mode) {
    if (state.publicFilterLoading) {
      return `<div class="mmwInviteHintCard">正在加载哈士奇同款筛选参数…</div>`;
    }
    if (!state.publicFilterHeaders.length) {
      return `<div class="mmwInviteHintCard">暂未拿到抖店筛选参数，请稍后重试。</div>`;
    }

    const form = getModeForm(mode);
    return `
      <div class="mmwInviteFilterSchema mmwInviteFilterSchema--hsq">
        ${state.publicFilterHeaders.map((group, index) => renderPublicFilterGroup(group, form, mode, index)).join("")}
      </div>
    `;
  }

  function renderPublicFilterGroup(group, form, mode, index = 0) {
    if (!group || !Array.isArray(group.header) || !group.header.length) return "";
    const title = String(group.name || "").trim();
    if (!title) return "";
    const groupKey = `public:${mode}:${index}`;
    const foldable = !/达人信息/.test(title) && index < 3;
    const defaultExpanded = !foldable;
    const groupClassName = getPublicFilterGroupClass(title, index);

    if (isGroupTextOnly(group.header)) {
      const values = Array.isArray(form.filters[PUBLIC_FILTER_FIELDS.contentType]) ? form.filters[PUBLIC_FILTER_FIELDS.contentType] : [];
      return renderFilterGroupShell({
        title,
        groupKey,
        defaultExpanded,
        foldable,
        bodyClassName: groupClassName,
        bodyHtml: `
          <div class="mmwInviteChipGroup">
            <button
              type="button"
              class="mmwInviteChip ${values.length === 0 ? "is-active" : ""}"
              data-action="togglePublicFilter"
              data-mode="${mode}"
              data-field="${PUBLIC_FILTER_FIELDS.contentType}"
              data-value="全部"
              data-kind="all"
            >全部</button>
            ${group.header.map((item) => {
              const active = valuesContain(values, item.value);
              return `
                <button
                  type="button"
                  class="mmwInviteChip ${active ? "is-active" : ""}"
                  data-action="togglePublicFilter"
                  data-mode="${mode}"
                  data-field="${PUBLIC_FILTER_FIELDS.contentType}"
                  data-value="${escapeHtml(String(item.value ?? ""))}"
                  data-value-type="${getValueType(item.value)}"
                  data-kind="multi"
                >${escapeHtml(item.name || "")}</button>
              `;
            }).join("")}
          </div>
        `
      });
    }

    const items = expandAggChildren(group.header).filter(Boolean);
    const controls = items.map((item) => renderPublicFilterItem(item, form, mode)).filter(Boolean).join("");
    if (!controls) return "";

    return renderFilterGroupShell({
      title,
      groupKey,
      defaultExpanded,
      foldable,
      bodyClassName: groupClassName,
      bodyHtml: `<div class="mmwInviteFilterGrid">${controls}</div>`
    });
  }

  function getPublicFilterGroupClass(title, index) {
    if (/主推类目/.test(title)) return "mmwInviteFilterGroup--mainCate";
    if (/内容类型/.test(title)) return "mmwInviteFilterGroup--contentType";
    if (/带货数据/.test(title)) return "mmwInviteFilterGroup--commerceData";
    if (/达人信息/.test(title)) return "mmwInviteFilterGroup--talentInfo";
    return `mmwInviteFilterGroup--public${index}`;
  }

  function renderPublicFilterItem(item, form, mode) {
    const field = String(item?.field_name || "").trim();
    if (!field) return "";

    if (item.type === "checkbox" || item.type === "ratio") {
      const values = Array.isArray(form.filters[field]) ? form.filters[field] : [];
      const options = Array.isArray(item.children) ? item.children.filter((option) => option?.value !== undefined) : [];
      if (!options.length) return "";
      const selectedKey = values.length ? valueKey(values[0]) : "";
      return `
        <div class="mmwInviteSubField mmwInviteSubField--select">
          <select
            class="mmwInviteInput mmwInvitePublicSelect ${selectedKey ? "is-active" : ""}"
            data-role="public-filter-select"
            data-mode="${mode}"
            data-field="${escapeHtml(field)}"
          >
            <option value="">${escapeHtml(item.name || "请选择")}</option>
            ${options.map((option) => `<option
              value="${escapeHtml(String(option.value ?? ""))}"
              data-value-type="${getValueType(option.value)}"
              ${selectedKey === valueKey(option.value) ? "selected" : ""}
              ${option.invalid ? "disabled" : ""}
            >${escapeHtml(option.name || "")}</option>`).join("")}
          </select>
        </div>
      `;
    }

    if (item.type === "bool") {
      const values = Array.isArray(form.filters[field]) ? form.filters[field] : [];
      const active = valuesContain(values, item.value);
      return `
        <div class="mmwInviteSubField">
          <button
            type="button"
            class="mmwInviteChip ${active ? "is-active" : ""}"
            data-action="togglePublicFilter"
            data-mode="${mode}"
            data-field="${escapeHtml(field)}"
            data-value="${escapeHtml(String(item.value ?? ""))}"
            data-value-type="${getValueType(item.value)}"
            data-kind="single"
          >${escapeHtml(item.name || "")}</button>
        </div>
      `;
    }

    if (item.type === "cascade") {
      const headerKey = getHeaderKey(item);
      const pathMap = normalizePlainObject(form.cascadePaths);
      const path = Array.isArray(pathMap[headerKey]) ? pathMap[headerKey] : [];
      const levels = buildCascadeLevels(item.children || [], path);
      return `
        <div class="mmwInviteSubField mmwInviteSubField--cascade">
          <div class="mmwInviteCascadeBox">
            <div class="mmwInviteCascadeSelects">
              ${levels.map((options, level) => `
                <select
                  class="mmwInviteInput mmwInviteCascadeSelect"
                  data-action="updateCascade"
                  data-mode="${mode}"
                  data-header-key="${escapeHtml(headerKey)}"
                  data-level="${level}"
                >
                  <option value="">${level === 0 ? escapeHtml(item.name || "请选择") : "请选择"}</option>
                  ${options.map((option) => `<option value="${escapeHtml(String(option.value ?? ""))}" data-value-type="${getValueType(option.value)}" ${String(path[level] ?? "") === String(option.value ?? "") ? "selected" : ""}>${escapeHtml(option.name || "")}</option>`).join("")}
                </select>
              `).join("")}
            </div>
            ${path.length ? `<button type="button" class="mmwInviteTinyTextButton" data-action="clearCascade" data-mode="${mode}" data-header-key="${escapeHtml(headerKey)}">清空</button>` : ""}
          </div>
        </div>
      `;
    }

    return "";
  }

  function renderCandidateList(title, list, action, source, type) {
    if (!Array.isArray(list) || !list.length) return "";
    return `
      <div class="mmwInviteSuggestionBlock">
        <div class="mmwInviteSuggestionTitle">${escapeHtml(title)}</div>
        <div class="mmwInviteSuggestionGrid">
          ${list.map((item, index) => `
            <button
              type="button"
              class="mmwInviteSuggestionCard"
              data-action="${action}"
              data-source="${source}"
              data-index="${index}"
            >
              <div class="mmwInviteSuggestionMain">
                ${item.avatar || item.cover ? `<img src="${escapeHtml(item.avatar || item.cover)}" alt="">` : `<span class="mmwInviteSuggestionPlaceholder">${type === "author" ? "达" : "货"}</span>`}
                <div class="mmwInviteSuggestionInfo">
                  <div class="mmwInviteSuggestionName">${escapeHtml(type === "author" ? (item.nickname || item.author_name || "") : (item.product_name || ""))}</div>
                  <div class="mmwInviteSuggestionMeta">${type === "author"
                    ? `${escapeHtml(formatNumber(item.fans_num || item.fans || 0))} 粉丝${item.main_cate_text ? ` · ${escapeHtml(item.main_cate_text)}` : ""}`
                    : `ID:${escapeHtml(String(item.product_id || ""))}${renderProductPriceMeta(item)}`}</div>
                </div>
              </div>
            </button>
          `).join("")}
        </div>
      </div>
    `;
  }

  function renderSendCard() {
    const node = document.getElementById(IDS.sendCard);
    if (!node) return;
    const workspace = node.closest(".mmwInviteWorkspace");
    workspace?.classList.toggle("has-send-panel", Boolean(state.sendDialogOpen));

    if (!state.sendDialogOpen) {
      node.className = "mmwInviteSendDock";
      node.innerHTML = "";
      return;
    }

    const selectedProducts = normalizeSelectedProductList(state.form.selectedProducts || []);
    node.className = "mmwInviteSendDock is-open";
    node.innerHTML = `
      <section class="mmwInviteSendPanel" role="region" aria-label="发送合作邀约">
        <div class="mmwInviteSendHeader">
          <div>
            <div class="mmwInviteSectionTitle">发送合作邀约</div>
            <div class="mmwInviteSectionDesc">已选择 ${state.selected.size} 位达人，确认邀约信息、权益和推荐商品后发送。</div>
          </div>
          <button type="button" class="mmwInviteSendClose" data-action="closeSendDialog" aria-label="关闭">×</button>
        </div>
        <div class="mmwInviteForm">
          <label class="mmwInviteField">
            <span>邀约信息</span>
            <textarea id="${IDS.inviteText}" class="mmwInviteTextarea" maxlength="150" rows="5">${escapeHtml(state.form.inviteText || DEFAULT_INVITE_TEXT)}</textarea>
          </label>

          <div class="mmwInviteField">
            <span>专属权益</span>
            <div class="mmwInviteRightsGrid">
              ${RIGHTS_OPTIONS.map((right) => `
                <label class="mmwInviteCheckItem">
                  <input type="checkbox" data-role="invite-right" value="${escapeHtml(right)}" ${normalizeRights(state.form.rights).includes(right) ? "checked" : ""}>
                  <span>${escapeHtml(right)}</span>
                </label>
              `).join("")}
            </div>
          </div>

          <div class="mmwInviteTwoCols">
            <label class="mmwInviteField">
              <span>手机号</span>
              <input id="${IDS.phone}" class="mmwInviteInput" value="${escapeHtml(state.form.phone || "")}" placeholder="可留空，优先读取抖店默认联系方式">
            </label>
            <label class="mmwInviteField">
              <span>微信号</span>
              <input id="${IDS.wechat}" class="mmwInviteInput" value="${escapeHtml(state.form.wechat || "")}" placeholder="可留空">
            </label>
          </div>

          <label class="mmwInviteField">
            <span>默认专属佣金（可选）</span>
            <input id="${IDS.commissionRatio}" class="mmwInviteInput" type="number" min="0" max="100" value="${escapeHtml(state.form.commissionRatio || "")}" placeholder="例如 20">
          </label>

          <div class="mmwInviteField">
            <span>推荐商品</span>
            <div class="mmwInviteSearchLine">
              <input id="${IDS.storeProductQuery}" class="mmwInviteInput" value="${escapeHtml(state.form.storeProductQuery || "")}" placeholder="输入商品名称或商品 ID 加载店铺商品">
              <button type="button" class="mmwInviteSubAction" data-action="searchStoreProducts">${state.storeProductsLoading ? "加载中…" : "加载商品"}</button>
            </div>
            ${renderStoreProductLibrary()}
            <div class="mmwInviteSelectedProducts">
              <div class="mmwInviteSelectedProductsTitle">已添加 ${selectedProducts.length}/${MAX_INVITE_PRODUCTS} 个推荐商品</div>
              ${renderSelectedProductTable(selectedProducts)}
            </div>
          </div>

          <div class="mmwInviteSendFooter">
            <div class="mmwInviteHint">默认每批 10 个达人；遇到频繁、风控、滑块等情况会自动降级为单个发送。</div>
            <div class="mmwInviteSendActions">
              <button class="mmwInviteCancelButton" type="button" data-action="closeSendDialog">取消</button>
              <button id="${IDS.sendButton}" class="mmwInviteActionButton mmwInviteInviteButton" type="button" data-action="sendInvites">${state.sending ? COPY.sendStop : COPY.send}</button>
            </div>
          </div>
        </div>
      </section>
    `;
    syncButtons();
  }

  function renderStoreProductLibrary() {
    if (state.storeProductsLoading && !state.storeProducts.length) {
      return `<div class="mmwInviteHintCard">正在加载店铺商品…</div>`;
    }

    if (!state.storeProducts.length) {
      return `<div class="mmwInviteHintCard">还没有加载店铺商品，点“加载商品”后即可勾选推送。</div>`;
    }

    const selectedIds = new Set((state.form.selectedProducts || []).map((item) => String(item.product_id)));
    return `
      <div class="mmwInviteProductLibrary">
        <div class="mmwInviteProductGrid">
          ${state.storeProducts.map((item) => {
            const active = selectedIds.has(String(item.product_id));
            return `
              <div class="mmwInviteProductCard ${active ? "is-active" : ""}">
                <div class="mmwInviteProductCardMain">
                  ${item.cover ? `<img src="${escapeHtml(item.cover)}" alt="">` : `<span class="mmwInviteSuggestionPlaceholder">货</span>`}
                  <div class="mmwInviteProductCardInfo">
                    <div class="mmwInviteProductCardName">${escapeHtml(item.product_name || "")}</div>
                    <div class="mmwInviteProductCardMeta">ID:${escapeHtml(String(item.product_id || ""))}${renderProductPriceMeta(item)}</div>
                  </div>
                </div>
                <button type="button" class="mmwInviteTinyAction ${active ? "is-active" : ""}" data-action="toggleStoreProduct" data-product-id="${escapeHtml(String(item.product_id || ""))}">
                  ${active ? "已添加" : "添加商品"}
                </button>
              </div>
            `;
          }).join("")}
        </div>
        ${state.storeProductHasMore ? `<div class="mmwInviteLibraryFooter"><button type="button" class="mmwInviteSubtleButton" data-action="loadMoreStoreProducts">${state.storeProductsLoading ? "加载中…" : "加载更多"}</button></div>` : ""}
      </div>
    `;
  }

  function renderSelectedProductTable(list) {
    if (!list.length) {
      return `<div class="mmwInviteHintCard">还没有选择推荐商品。</div>`;
    }

    return `
      <div class="mmwInviteTableWrap mmwInviteTableWrap--products">
        <table class="mmwInviteTable">
          <thead>
            <tr>
              <th>商品信息</th>
              <th>专属佣金</th>
              <th>免费申样</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            ${list.map((item) => `
              <tr>
                <td>
                  <div class="mmwInviteTalentCell">
                    ${item.cover ? `<img class="mmwInviteSelectedThumb" src="${escapeHtml(item.cover)}" alt="">` : ""}
                    <div>
                      <div class="mmwInviteTalentName">${escapeHtml(item.product_name || item.product_id || "")}</div>
                      <div class="mmwInviteMuted">ID: ${escapeHtml(String(item.product_id || ""))}${renderProductPriceMeta(item)}</div>
                    </div>
                  </div>
                </td>
                <td>
                  <input
                    class="mmwInviteInput mmwInviteMiniInput"
                    type="number"
                    min="0"
                    max="100"
                    value="${escapeHtml(item.customCommissionRatio || "")}"
                    placeholder="${escapeHtml(state.form.commissionRatio || "跟随默认")}"
                    data-role="selected-product-commission"
                    data-product-id="${escapeHtml(String(item.product_id || ""))}"
                  >
                </td>
                <td>
                  <label class="mmwInviteCheckItem mmwInviteCheckItem--inline">
                    <input
                      type="checkbox"
                      data-role="selected-product-sample"
                      data-product-id="${escapeHtml(String(item.product_id || ""))}"
                      ${Number(item.author_sample_status ?? 1) === 1 ? "checked" : ""}
                    >
                    <span>开启</span>
                  </label>
                </td>
                <td>
                  <button type="button" class="mmwInviteTinyTextButton" data-action="removeSelectedProduct" data-product-id="${escapeHtml(String(item.product_id || ""))}">删除</button>
                </td>
              </tr>
            `).join("")}
          </tbody>
        </table>
      </div>
    `;
  }

  function renderTalentTable() {
    const body = document.getElementById(IDS.tableBody);
    if (!body) return;

    const talents = Array.from(state.talents.values());
    if (!talents.length) {
      body.innerHTML = `<tr><td colspan="9" class="mmwInviteEmpty">还没有加载达人</td></tr>`;
      syncCounts();
      return;
    }

    body.innerHTML = talents.map((talent, index) => `
      <tr class="${talent.resultType ? `is-${talent.resultType}` : ""}">
        <td class="mmwInviteTableColId">${index + 1}</td>
        <td>
          <input type="checkbox" data-uid="${escapeHtml(talent.uid)}" ${state.selected.has(talent.uid) ? "checked" : ""} ${talent.resultType === "success" ? "disabled" : ""}>
        </td>
        <td>
          <div class="mmwInviteTalentCell">
            ${talent.avatar ? `<img src="${escapeHtml(talent.avatar)}" alt="">` : ""}
            <div>
              <div class="mmwInviteTalentName">${escapeHtml(talent.nickname)}</div>
              <a class="mmwInviteTalentUid" href="${escapeHtml(talent.profileUrl)}" target="_blank" rel="noreferrer" title="${escapeHtml(talent.uid)}">${escapeHtml(formatShortId(talent.uid))}</a>
              <div class="mmwInviteTalentMeta">${escapeHtml([talent.mainCate, talent.location].filter(Boolean).join(" | ") || "-")}</div>
            </div>
          </div>
        </td>
        <td class="mmwInviteMetricCell">${escapeHtml(formatTalentMetric(talent.fans, true))}</td>
        <td class="mmwInviteMetricCell">${escapeHtml(formatTalentMetric(talent.settlementTotal))}</td>
        <td class="mmwInviteMetricCell">${escapeHtml(formatTalentMetric(talent.liveSettlement))}</td>
        <td class="mmwInviteMetricCell">${escapeHtml(formatTalentMetric(talent.videoSettlement))}</td>
        <td class="mmwInviteMetricCell">${escapeHtml(formatTalentMetric(talent.imageTextSettlement))}</td>
        <td>
          <span class="mmwInviteResult ${talent.resultType ? `is-${talent.resultType}` : ""}">
            ${escapeHtml(talent.resultText || "可邀约")}
          </span>
        </td>
      </tr>
    `).join("");

    syncCounts();
  }

  function renderFilteredTable() {
    const body = document.getElementById(IDS.filteredBody);
    if (!body) return;

    const filtered = Array.from(state.filtered.values());
    if (!filtered.length) {
      body.innerHTML = `<tr><td colspan="2" class="mmwInviteEmpty">暂无过滤记录</td></tr>`;
      syncCounts();
      return;
    }

    body.innerHTML = filtered.map((item) => `
      <tr>
        <td>
          <div class="mmwInviteTalentName">${escapeHtml(item.nickname || item.uid || COPY.unnamed)}</div>
          <div class="mmwInviteMuted">${escapeHtml(item.uid || "")}</div>
        </td>
        <td>${escapeHtml(item.reason || "不可邀约")}</td>
      </tr>
    `).join("");

    syncCounts();
  }

  function syncAll() {
    syncCounts();
    syncButtons();
    if (state.sendDialogOpen) renderSendCard();
  }

  function syncCounts() {
    const count = document.getElementById(IDS.count);
    const filtered = document.getElementById(IDS.filtered);
    const selected = document.getElementById(IDS.selected);
    if (count) count.textContent = `已加载 ${state.talents.size} 位达人${state.total ? ` / 抖店共 ${state.total} 位` : ""}`;
    if (filtered) filtered.textContent = `已过滤 ${state.filtered.size} 位不可邀约达人`;
    if (selected) selected.textContent = `已选择 ${state.selected.size} 位`;

    const selectAll = document.getElementById(IDS.selectAll);
    if (selectAll instanceof HTMLInputElement) {
      const total = state.talents.size;
      selectAll.checked = total > 0 && state.selected.size === total;
      selectAll.indeterminate = state.selected.size > 0 && state.selected.size < total;
      const headCount = selectAll.closest("label")?.querySelector("span");
      if (headCount) headCount.textContent = `${state.selected.size}/${total}`;
    }
  }

  function formatTalentMetric(value, isNumber) {
    if (value === undefined || value === null || value === "") return "-";
    if (typeof value === "number") return Number.isFinite(value) ? formatNumber(value) : "-";
    const text = String(value || "").trim();
    if (!text) return "-";
    return isNumber && /^-?\d+(\.\d+)?$/.test(text) ? formatNumber(Number(text)) : text;
  }

  function formatShortId(value) {
    const text = String(value || "").trim();
    if (text.length <= 22) return text;
    return `${text.slice(0, 12)}...${text.slice(-8)}`;
  }

  function syncButtons() {
    const loadButton = document.getElementById(IDS.loadButton);
    if (loadButton instanceof HTMLButtonElement) {
      loadButton.textContent = state.loading
        ? COPY.loadStop
        : (state.page > 1 && state.hasMore ? COPY.loadContinue : COPY.loadStart);
      loadButton.disabled = state.sending;
      loadButton.classList.toggle("is-disabled", loadButton.disabled);
    }

    const resetButton = document.getElementById(IDS.resetButton);
    if (resetButton instanceof HTMLButtonElement) {
      resetButton.disabled = state.loading || state.sending;
      resetButton.classList.toggle("is-disabled", resetButton.disabled);
    }

    const sendButton = document.getElementById(IDS.sendButton);
    if (sendButton instanceof HTMLButtonElement) {
      sendButton.textContent = state.sending ? COPY.sendStop : COPY.send;
      sendButton.disabled = state.loading || (!state.sending && state.selected.size === 0);
      sendButton.classList.toggle("is-disabled", sendButton.disabled);
    }

    const openSendButton = document.getElementById(IDS.openSendButton);
    if (openSendButton instanceof HTMLButtonElement) {
      openSendButton.disabled = state.loading || state.sending || state.selected.size === 0;
      openSendButton.classList.toggle("is-disabled", openSendButton.disabled);
    }

    const interval = document.getElementById(IDS.interval);
    if (interval instanceof HTMLSelectElement) {
      interval.disabled = state.loading || state.sending;
    }
  }

  function syncStatus(text) {
    const node = document.getElementById(IDS.status);
    if (node) node.textContent = String(text || "").trim() || COPY.statusReady;
  }

  function resetTalentState() {
    state.page = 1;
    state.total = 0;
    state.hasMore = true;
    state.talents.clear();
    state.filtered.clear();
    state.selected.clear();
    state.cardVersion = null;
  }

  function rememberMappedValue(bucket, field, value) {
    if (!field || value === undefined || value === null || value === "") return;
    if (!bucket[field]) bucket[field] = new Map();
    bucket[field].set(valueKey(value), value);
  }

  function collectCascadeFieldValues(children, bucket, depth = 0) {
    const cascadeField = [
      PUBLIC_FILTER_FIELDS.cateFirst,
      PUBLIC_FILTER_FIELDS.cateSecond,
      PUBLIC_FILTER_FIELDS.cateThird
    ][depth];
    if (!cascadeField || !Array.isArray(children)) return;
    children.forEach((child) => {
      rememberMappedValue(bucket, cascadeField, child?.value);
      if (Array.isArray(child?.children) && child.children.length) {
        collectCascadeFieldValues(child.children, bucket, depth + 1);
      }
    });
  }

  function collectPublicFieldValueMaps() {
    const bucket = {};

    (state.publicFilterHeaders || []).forEach((group) => {
      const headers = Array.isArray(group?.header) ? group.header : [];
      if (isGroupTextOnly(headers)) {
        headers.forEach((item) => rememberMappedValue(bucket, PUBLIC_FILTER_FIELDS.contentType, item?.value));
        return;
      }

      const walk = (item) => {
        if (!item) return;
        const field = String(item.field_name || "").trim();
        if (item.type === "checkbox" || item.type === "ratio") {
          (item.children || []).forEach((option) => rememberMappedValue(bucket, field, option?.value));
          return;
        }
        if (item.type === "bool") {
          rememberMappedValue(bucket, field, item.value);
          return;
        }
        if (item.type === "cascade") {
          rememberMappedValue(bucket, field, item.value);
          if (field === PUBLIC_FILTER_FIELDS.mainCateNew) {
            collectCascadeFieldValues(item.children || [], bucket, 0);
          } else {
            const walkCascade = (children) => {
              (children || []).forEach((option) => {
                rememberMappedValue(bucket, field, option?.value);
                if (Array.isArray(option?.children) && option.children.length) {
                  walkCascade(option.children);
                }
              });
            };
            walkCascade(item.children || []);
          }
          return;
        }
        if (item.type === "agg" && Array.isArray(item.children)) {
          item.children.forEach(walk);
        }
      };

      headers.forEach(walk);
    });

    return bucket;
  }

  function collectRecFieldValueMaps() {
    const bucket = {};
    const sections = [
      ...(Array.isArray(state.recListSchema?.option_headers_list?.[0]) ? state.recListSchema.option_headers_list[0] : []),
      ...(Array.isArray(state.recListSchema?.base_headers) ? state.recListSchema.base_headers : [])
    ];
    sections.forEach((section) => {
      (section?.header || []).forEach((item) => {
        rememberMappedValue(bucket, item?.field_name, item?.value);
      });
    });
    return bucket;
  }

  function resolveMappedValue(fieldMaps, field, rawValue) {
    const mapped = fieldMaps?.[field];
    if (!mapped) return rawValue;
    return mapped.get(valueKey(rawValue)) ?? rawValue;
  }

  function coercePublicFiltersForRequest(filters) {
    const fieldMaps = collectPublicFieldValueMaps();
    const source = normalizePlainObject(filters);
    const next = {};
    Object.entries(source).forEach(([field, values]) => {
      next[field] = Array.isArray(values)
        ? values.map((value) => resolveMappedValue(fieldMaps, field, value))
        : values;
    });
    return next;
  }

  function coerceRecFiltersForRequest(form) {
    const fieldMaps = collectRecFieldValueMaps();
    return {
      author_type: normalizeSelectableValues(form.author_type).map((value) => resolveMappedValue(fieldMaps, "author_type", value)),
      target_crowd: normalizeSelectableValues(form.target_crowd).map((value) => resolveMappedValue(fieldMaps, "target_crowd", value)),
      matching_method: normalizeSelectableValues(form.matching_method).map((value) => resolveMappedValue(fieldMaps, "matching_method", value)),
      main_cate: normalizeSelectableValues(form.main_cate).map((value) => resolveMappedValue(fieldMaps, "main_cate", value))
    };
  }

  function buildDefaultPublicFilters(groups, presetMerchantInfo = false) {
    const result = {};
    (groups || []).forEach((group) => {
      (group?.header || []).forEach((item) => {
        if (!item?.field_name) return;
        if (["text", "checkbox", "ratio", "cascade", "bool"].includes(item.type)) {
          if (item.field_name === PUBLIC_FILTER_FIELDS.merchantInfo && presetMerchantInfo) {
            result[item.field_name] = ["1"];
          } else if (!(item.field_name in result)) {
            result[item.field_name] = [];
          }
        }
        if (item.type === "agg" && Array.isArray(item.children)) {
          if (!(item.field_name in result)) result[item.field_name] = [];
          Object.assign(result, buildAggChildrenDefaults(item.children));
        }
      });
    });
    return result;
  }

  function buildAggChildrenDefaults(children) {
    const result = {};
    (children || []).forEach((item) => {
      if (!item?.field_name) return;
      result[item.field_name] = [];
    });
    return result;
  }

  function mergeFilterDefaults(current, defaults) {
    const next = cloneJson(defaults);
    const source = normalizePlainObject(current);
    Object.entries(source).forEach(([key, value]) => {
      next[key] = Array.isArray(value) ? [...value] : value;
    });
    return next;
  }

  function findPublicHeaderItem(headerKey) {
    for (const group of state.publicFilterHeaders) {
      for (const item of group?.header || []) {
        const found = findHeaderItemRecursive(item, headerKey);
        if (found) return found;
      }
    }
    return null;
  }

  function findHeaderItemRecursive(item, headerKey) {
    if (!item) return null;
    if (getHeaderKey(item) === headerKey) return item;
    if (Array.isArray(item.children)) {
      for (const child of item.children) {
        const found = findHeaderItemRecursive(child, headerKey);
        if (found) return found;
      }
    }
    return null;
  }

  function getHeaderKey(item) {
    return `${item?.field_name || ""}::${item?.value ?? item?.name ?? ""}`;
  }

  function buildCascadeLevels(children, path) {
    const levels = [];
    let currentOptions = Array.isArray(children) ? children : [];
    let depth = 0;
    while (currentOptions.length) {
      levels.push(currentOptions);
      const selectedValue = path[depth];
      const selected = currentOptions.find((item) => String(item.value) === String(selectedValue));
      if (!selected || !Array.isArray(selected.children) || !selected.children.length) break;
      currentOptions = selected.children;
      depth += 1;
    }
    return levels;
  }

  function expandAggChildren(items) {
    const result = [];
    (items || []).forEach((item) => {
      if (item?.type === "agg" && Array.isArray(item.children)) {
        result.push(...item.children);
      } else {
        result.push(item);
      }
    });
    return result;
  }

  function isGroupTextOnly(items) {
    return Array.isArray(items) && items.length > 0 && items[0]?.type === "text";
  }

  function normalizeListResponse(data) {
    const source = data?.data || data || {};
    const rawList = source.list || source.author_list || source.authors || [];
    const list = Array.isArray(rawList)
      ? rawList.map((item) => item?.author_data || item).filter(Boolean)
      : [];
    return {
      list,
      total: Number(source.total || source.total_count || source.count || list.length || 0),
      hasMore: Boolean(source.has_more ?? source.hasMore ?? source.has_next ?? list.length > 0)
    };
  }

  function normalizeTalent(raw) {
    const base = raw?.author_base || raw?.author_info || raw || {};
    const connection = raw?.author_connection || raw?.connection || {};
    const fans = pickTalentMetric(raw, [
      "fans_num_text",
      "fans_count_text",
      "fans_num",
      "fans_count",
      "follower_count",
      "follower_num",
      "fans"
    ]);
    const uid = pickTalentId(raw, base);
    const accountId = pickTalentAccountId(raw, base, uid);
    const nickname = String(base.nickname || base.name || raw?.nickname || COPY.unnamed).trim();
    const imStatus = Number(connection.im_status ?? connection.status ?? raw?.im_status ?? 0);
    const hoverText = String(connection.im_hover_text || connection.hover_text || connection.reason || "").trim();
    const reason = getFilterReason(imStatus, hoverText, Boolean(connection.im_status ?? connection.status ?? raw?.im_status !== undefined));
    const mainCate = getMainCate(raw, base);
    return {
      raw,
      uid,
      accountId,
      nickname,
      avatar: base.avatar || base.avatar_url || "",
      fans: fans || base.fans_num || base.fans || raw?.fans_num || 0,
      mainCate,
      location: getTalentLocation(raw, base),
      settlementTotal: pickTalentMetric(raw, [
        "settlement_amount_range_text",
        "settle_amount_range_text",
        "total_settlement_amount_range",
        "total_settle_amount_range",
        "settlement_amount_range",
        "settle_amount_range",
        "total_sales_amount_range",
        "sales_amount_range",
        "total_gmv_range",
        "pay_gmv_range",
        "gmv_range",
        "total_settlement_text",
        "total_settle_text",
        "settlement_amount_text",
        "settle_amount_text",
        "total_sales_text",
        "gmv_text"
      ]),
      liveSettlement: pickTalentMetric(raw, [
        "live_settlement_amount_range_text",
        "live_settle_amount_range_text",
        "live_settlement_amount_range",
        "live_settle_amount_range",
        "live_sales_amount_range",
        "live_pay_gmv_range",
        "live_gmv_range",
        "live_amount_range",
        "live_settlement_text",
        "live_settle_text",
        "live_sales_text",
        "live_gmv_text"
      ]),
      videoSettlement: pickTalentMetric(raw, [
        "video_settlement_amount_range_text",
        "video_settle_amount_range_text",
        "short_video_settlement_amount_range",
        "short_video_settle_amount_range",
        "video_settlement_amount_range",
        "video_settle_amount_range",
        "short_video_sales_amount_range",
        "video_sales_amount_range",
        "video_pay_gmv_range",
        "video_gmv_range",
        "video_amount_range",
        "video_settlement_text",
        "video_settle_text",
        "video_sales_text",
        "video_gmv_text"
      ]),
      imageTextSettlement: pickTalentMetric(raw, [
        "image_text_settlement_amount_range_text",
        "image_text_settle_amount_range_text",
        "image_text_settlement_amount_range",
        "image_text_settle_amount_range",
        "image_text_sales_amount_range",
        "image_text_pay_gmv_range",
        "image_text_gmv_range",
        "graphic_settlement_amount_range",
        "graphic_settle_amount_range",
        "graphic_sales_amount_range",
        "graphic_gmv_range",
        "article_settlement_amount_range",
        "article_sales_amount_range",
        "note_settlement_amount_range",
        "note_sales_amount_range",
        "pic_text_settlement_amount_range",
        "pic_text_sales_amount_range",
        "picture_text_settlement_amount_range",
        "picture_text_sales_amount_range",
        "img_text_settlement_amount_range",
        "img_text_sales_amount_range",
        "image_text_settlement_text",
        "image_text_settle_text",
        "image_text_sales_text",
        "graphic_sales_text"
      ]),
      imStatus,
      reason,
      profileUrl: uid ? `https://buyin.jinritemai.com/dashboard/servicehall/daren-profile?uid=${encodeURIComponent(uid)}` : "",
      resultType: "",
      resultText: ""
    };
  }

  function pickTalentId(raw, base) {
    return firstTalentId(
      base?.uid,
      base?.author_id,
      raw?.author_id,
      raw?.uid,
      base?.id,
      base?.user_id,
      base?.author_id_str,
      base?.uid_str,
      raw?.id,
      raw?.user_id,
      raw?.author_id_str,
      raw?.uid_str,
      raw?.base_info?.uid,
      raw?.base_info?.author_id,
      raw?.author?.uid,
      raw?.author?.author_id
    );
  }

  function pickTalentAccountId(raw, base, fallback) {
    return firstTalentId(
      base?.uid,
      raw?.uid,
      base?.author_id_str,
      raw?.author_id_str,
      base?.uid_str,
      raw?.uid_str,
      base?.author_id,
      raw?.author_id,
      base?.id,
      raw?.id,
      fallback
    );
  }

  function firstTalentId(...values) {
    for (const value of values) {
      const normalized = normalizeTalentIdValue(value);
      if (normalized) return normalized;
    }
    return "";
  }

  function normalizeTalentIdValue(value) {
    if (value === undefined || value === null || value === "") return "";
    if (typeof value === "object") {
      return firstTalentId(value.uid, value.author_id, value.id, value.user_id, value.value);
    }
    const text = String(value).trim();
    return text && text !== "0" ? text : "";
  }

  function getMainCate(raw, base) {
    const tag = raw?.author_tag || base?.author_tag || {};
    const cate = tag.work_cate || base?.main_cate || raw?.main_cate || raw?.categories || [];
    if (Array.isArray(cate)) return cate.filter(Boolean).join("/");
    return String(cate || "").trim();
  }

  function getTalentLocation(raw, base) {
    const tag = raw?.author_tag || base?.author_tag || {};
    const location = firstNonEmpty(
      base.province_city,
      base.city_name,
      base.city,
      base.province,
      base.location,
      base.author_location,
      raw?.province_city,
      raw?.city_name,
      raw?.city,
      raw?.province,
      raw?.location,
      raw?.author_location,
      tag.province_city,
      tag.city_name,
      tag.city,
      tag.province,
      tag.location
    );
    if (Array.isArray(location)) return location.filter(Boolean).join("/");
    return String(location || "").trim();
  }

  function pickTalentMetric(source, keys) {
    for (const key of keys || []) {
      const value = findDeepValueByKey(source, normalizeMetricKey(key));
      const normalized = normalizeMetricValue(value);
      if (normalized !== "") return normalized;
    }
    return "";
  }

  function findDeepValueByKey(source, targetKey) {
    if (!source || !targetKey) return undefined;
    const queue = [{ value: source, depth: 0 }];
    const seen = new WeakSet();
    while (queue.length) {
      const current = queue.shift();
      const value = current.value;
      if (!value || typeof value !== "object") continue;
      if (seen.has(value)) continue;
      seen.add(value);
      if (Array.isArray(value)) {
        if (current.depth >= 5) continue;
        value.slice(0, 40).forEach((item) => queue.push({ value: item, depth: current.depth + 1 }));
        continue;
      }
      for (const [rawKey, rawValue] of Object.entries(value)) {
        if (normalizeMetricKey(rawKey) === targetKey) return rawValue;
      }
      if (current.depth >= 5) continue;
      for (const rawValue of Object.values(value)) {
        if (rawValue && typeof rawValue === "object") queue.push({ value: rawValue, depth: current.depth + 1 });
      }
    }
    return undefined;
  }

  function normalizeMetricKey(value) {
    return String(value || "").replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
  }

  function normalizeMetricValue(value) {
    if (value === undefined || value === null) return "";
    if (typeof value === "number") return Number.isFinite(value) ? value : "";
    if (typeof value === "string") return value.trim();
    if (Array.isArray(value)) {
      const parts = value.map(normalizeMetricValue).filter((item) => item !== "");
      return parts.length > 1 ? `${parts[0]} - ${parts[1]}` : (parts[0] || "");
    }
    if (typeof value === "object") {
      const text = firstNonEmpty(
        value.text,
        value.display_text,
        value.show_text,
        value.label,
        value.desc,
        value.value_text,
        value.value_str,
        value.range_text,
        value.range,
        value.amount_text
      );
      if (text !== "") return normalizeMetricValue(text);
      const min = firstNonEmpty(value.min, value.min_value, value.lower, value.low, value.start);
      const max = firstNonEmpty(value.max, value.max_value, value.upper, value.high, value.end);
      if (min !== "" || max !== "") {
        const minText = normalizeMetricValue(min);
        const maxText = normalizeMetricValue(max);
        return minText && maxText ? `${minText} - ${maxText}` : (minText || maxText);
      }
    }
    return "";
  }

  function firstNonEmpty(...values) {
    for (const value of values) {
      if (value === undefined || value === null) continue;
      if (typeof value === "string" && !value.trim()) continue;
      if (Array.isArray(value) && !value.length) continue;
      return value;
    }
    return "";
  }

  function getFilterReason(imStatus, hoverText, hasStatus) {
    if (!hasStatus) return "抖店返回缺少状态信息，无法发送邀约";
    if (imStatus === 1) return "";
    if (imStatus === 4) return "已经邀约，达人已回复";
    if (imStatus === 99) return hoverText ? `${hoverText}，请查看抖店规则` : "当前规则限制，无法邀约";
    return hoverText || "当前达人不可邀约";
  }

  function normalizeProductList(data) {
    const source = data?.data || data || {};
    const candidates = [
      source.list,
      source.data?.list,
      source.product_list,
      source.data?.product_list,
      source.products,
      source.data?.products,
      source.promotion_list,
      source.data?.promotion_list,
      source.goods_list,
      source.data?.goods_list,
      source.items,
      source.data?.items
    ];
    const directProductList = candidates.find((list) => Array.isArray(list) && list.some(looksLikeProductRecord));
    return directProductList || findProductArray(data) || candidates.find(Array.isArray) || [];
  }

  function normalizeProductCandidate(item) {
    const product = item?.prd_data || item?.product || item?.product_info || item?.goods || item?.promotion_product || item || {};
    const productId = firstNonEmpty(
      product.product_id,
      product.productId,
      product.productID,
      product.pid,
      product.id,
      item?.product_id,
      item?.productId,
      item?.pid,
      item?.id
    );
    const productName = firstNonEmpty(
      product.product_name,
      product.productName,
      product.title,
      product.name,
      product.goods_name,
      item?.product_name,
      item?.title,
      item?.name
    );
    const cover = firstNonEmpty(
      product.cover,
      product.cover_url,
      product.pic,
      product.pic_url,
      product.image,
      product.image_url,
      product.img,
      product.img_url,
      product.main_pic,
      product.product_img,
      item?.cover,
      item?.pic,
      item?.image
    );
    const orientDetail = firstNonEmpty(product.orient_cos_ratio_detail, item?.orient_cos_ratio_detail, {});
    const cosRatioRange = firstNonEmpty(product.cos_ratio_range, item?.cos_ratio_range, orientDetail?.cos_ratio_range, {});
    return {
      product_id: String(productId || "").trim(),
      product_name: String(productName || "").trim(),
      cover: String(cover || "").trim(),
      real_price_str: normalizeProductPriceText(product, item),
      author_sample_status: Number(firstNonEmpty(
        product.author_sample_status,
        item?.author_sample_status,
        product.sample?.author_sample_status,
        item?.sample?.author_sample_status,
        product.sample?.apply_style,
        item?.sample?.apply_style,
        1
      )),
      orient_cos_ratio_detail: cloneJson(orientDetail && typeof orientDetail === "object" ? orientDetail : {}),
      cos_ratio_range: cloneJson(cosRatioRange && typeof cosRatioRange === "object" ? cosRatioRange : {}),
      suggest_orient_kol_cos_ratio: firstNonEmpty(product.suggest_orient_kol_cos_ratio, item?.suggest_orient_kol_cos_ratio),
      cos_ratio: firstNonEmpty(product.cos_ratio, item?.cos_ratio),
      setOrientCosRatioDetail: cloneJson(firstNonEmpty(product.setOrientCosRatioDetail, item?.setOrientCosRatioDetail, {})),
      customCommissionRatio: String(firstNonEmpty(product.customCommissionRatio, item?.customCommissionRatio, ""))
    };
  }

  function findProductArray(data) {
    const queue = [{ value: data, depth: 0 }];
    while (queue.length) {
      const current = queue.shift();
      const value = current.value;
      if (!value || current.depth > 4) continue;
      if (Array.isArray(value)) {
        if (value.some(looksLikeProductRecord)) return value;
        value.slice(0, 20).forEach((item) => {
          if (item && typeof item === "object") queue.push({ value: item, depth: current.depth + 1 });
        });
        continue;
      }
      if (typeof value !== "object") continue;
      Object.values(value).forEach((item) => {
        if (item && typeof item === "object") queue.push({ value: item, depth: current.depth + 1 });
      });
    }
    return [];
  }

  function looksLikeProductRecord(item) {
    if (!item || typeof item !== "object") return false;
    const product = item.prd_data || item.product || item.product_info || item.goods || item.promotion_product || item;
    if (firstNonEmpty(product.product_id, product.productId, product.pid)) return true;
    return Boolean(product.id && firstNonEmpty(
      product.product_name,
      product.productName,
      product.title,
      product.name,
      product.goods_name,
      product.price,
      product.price_str,
      product.cover,
      product.pic,
      product.image
    ));
  }

  function renderProductPriceMeta(item) {
    const price = normalizePriceDisplay(firstNonEmpty(item?.real_price_str, item?.price_text, item?.price));
    return price ? ` · ¥ ${escapeHtml(price)}` : "";
  }

  function normalizeProductPriceText(...sources) {
    const textKeys = [
      "real_price_str",
      "price_str",
      "sell_price_str",
      "sale_price_str",
      "min_price_str",
      "show_price",
      "display_price",
      "price_text",
      "priceText"
    ];
    const amountKeys = [
      "real_price",
      "sell_price",
      "sale_price",
      "min_price",
      "price",
      "market_price",
      "origin_price"
    ];

    for (const source of sources) {
      if (!source || typeof source !== "object") continue;
      const text = firstNonEmpty(...textKeys.map((key) => source[key]));
      const normalizedText = normalizePriceDisplay(text);
      if (normalizedText) return normalizedText;
    }

    for (const source of sources) {
      if (!source || typeof source !== "object") continue;
      const amount = firstNonEmpty(...amountKeys.map((key) => source[key]));
      const normalizedAmount = normalizePriceDisplay(amount);
      if (normalizedAmount) return normalizedAmount;
    }

    return "";
  }

  function normalizePriceDisplay(value) {
    if (value === undefined || value === null) return "";
    const raw = String(value).trim();
    if (!raw) return "";

    const rangeParts = raw.split(/\s*(?:-|~|～|至)\s*/).filter(Boolean);
    if (rangeParts.length === 2) {
      const left = normalizePriceDisplay(rangeParts[0]);
      const right = normalizePriceDisplay(rangeParts[1]);
      return left && right ? `${left}-${right}` : (left || right);
    }

    const cleaned = raw.replace(/[￥¥元,]/g, "").trim();
    const match = cleaned.match(/\d+(?:\.\d+)?/);
    if (!match) return raw;

    const numericText = match[0];
    const amount = Number(numericText);
    if (!Number.isFinite(amount)) return raw;
    const yuan = shouldTreatAsFen(numericText, amount) ? amount / 100 : amount;
    return trimPriceZeros(yuan);
  }

  function shouldTreatAsFen(text, amount) {
    return !text.includes(".") && amount >= 100;
  }

  function trimPriceZeros(value) {
    return Number(value).toFixed(2).replace(/\.?0+$/, "");
  }

  function normalizeSelectedProductList(list) {
    return (Array.isArray(list) ? list : [])
      .map(normalizeProductCandidate)
      .filter((item) => item.product_id);
  }

  function normalizeSimilarSearchList(list) {
    return (Array.isArray(list) ? list : [])
      .map((item) => item?.author_info || item?.sugWord?.author_info || item)
      .map((item) => ({
        author_id: String(item?.author_id || item?.uid || "").trim(),
        nickname: String(item?.nickname || item?.name || "").trim(),
        avatar: String(item?.avatar || item?.avatar_url || "").trim(),
        fans_num: Number(item?.fans_num || item?.fans || 0),
        main_cate_text: Array.isArray(item?.main_cate) ? item.main_cate.join("/") : String(item?.main_cate || "")
      }))
      .filter((item) => item.author_id);
  }

  function normalizeSimilarSuggestList(list) {
    return (Array.isArray(list) ? list : [])
      .map((item) => {
        const info = item?.sugWord?.author_info || item?.author_info || item;
        return {
          author_id: String(info?.author_id || info?.uid || "").trim(),
          nickname: String(info?.nickname || info?.name || "").trim(),
          avatar: String(info?.avatar || info?.avatar_url || "").trim(),
          fans_num: Number(info?.fans_num || info?.fans || 0),
          main_cate_text: Array.isArray(info?.main_cate) ? info.main_cate.join("/") : String(info?.main_cate || ""),
          type: String(item?.type || "").trim()
        };
      })
      .filter((item) => item.author_id);
  }

  function mergeProducts(source, extra) {
    const map = new Map(source.map((item) => [String(item.product_id), item]));
    extra.forEach((item) => {
      map.set(String(item.product_id), item);
    });
    return Array.from(map.values());
  }

  function normalizeRights(rights) {
    if (Array.isArray(rights)) {
      return rights.map((item) => String(item || "").trim()).filter(Boolean);
    }
    return parseTextList(rights);
  }

  async function saveFormState() {
    try {
      const payload = cloneJson({
        ...state.form,
        selectedProducts: normalizeSelectedProductList(state.form.selectedProducts || []),
        rights: normalizeRights(state.form.rights),
        intervalSeconds: normalizeInterval(state.form.intervalSeconds),
        activeMode: state.form.activeMode || MODES.FIND_DAREN
      });
      await chrome.storage.local.set({
        [FORM_KEY]: payload,
        [INTERVAL_KEY]: payload.intervalSeconds
      });
    } catch {}
  }

  async function readFormState() {
    const keys = [FORM_KEY, ...LEGACY_FORM_KEYS];
    const values = await chrome.storage.local.get(keys).catch(() => ({}));
    const stored = values[FORM_KEY] || values[LEGACY_FORM_KEYS[0]] || null;
    return migrateStoredForm(stored);
  }

  function migrateStoredForm(stored) {
    const base = createDefaultForm();
    if (!stored || typeof stored !== "object") return base;

    if (stored.modes) {
      const storedExpandedGroups = normalizePlainObject(stored.expandedGroups);
      const normalizedExpandedGroups = Number(stored.expandedGroupsVersion || 0) >= 2
        ? storedExpandedGroups
        : Object.fromEntries(
            Object.entries(storedExpandedGroups).filter(([key]) => !String(key || "").startsWith("public:"))
          );
      const next = {
        ...base,
        ...stored,
        expandedGroupsVersion: 2,
        expandedGroups: normalizedExpandedGroups,
        rights: normalizeRights(stored.rights),
        talentColumns: normalizeTalentColumns(stored.talentColumns),
        selectedProducts: normalizeSelectedProductList(stored.selectedProducts || []),
        modes: {
          ...base.modes,
          ...stored.modes,
          [MODES.FIND_DAREN]: {
            ...base.modes[MODES.FIND_DAREN],
            ...(stored.modes[MODES.FIND_DAREN] || {}),
            filters: normalizePlainObject(stored.modes[MODES.FIND_DAREN]?.filters),
            cascadePaths: normalizePlainObject(stored.modes[MODES.FIND_DAREN]?.cascadePaths)
          },
          [MODES.SIMILAR_KOL]: {
            ...base.modes[MODES.SIMILAR_KOL],
            ...(stored.modes[MODES.SIMILAR_KOL] || {}),
            filters: normalizePlainObject(stored.modes[MODES.SIMILAR_KOL]?.filters),
            cascadePaths: normalizePlainObject(stored.modes[MODES.SIMILAR_KOL]?.cascadePaths)
          },
          [MODES.PRD_2_KOL]: {
            ...base.modes[MODES.PRD_2_KOL],
            ...(stored.modes[MODES.PRD_2_KOL] || {}),
            filters: normalizePlainObject(stored.modes[MODES.PRD_2_KOL]?.filters),
            cascadePaths: normalizePlainObject(stored.modes[MODES.PRD_2_KOL]?.cascadePaths)
          },
          [MODES.REC_LIST]: {
            ...base.modes[MODES.REC_LIST],
            ...(stored.modes[MODES.REC_LIST] || {}),
            author_type: normalizeStringArray(stored.modes[MODES.REC_LIST]?.author_type),
            target_crowd: normalizeStringArray(stored.modes[MODES.REC_LIST]?.target_crowd),
            matching_method: normalizeStringArray(stored.modes[MODES.REC_LIST]?.matching_method),
            main_cate: normalizeStringArray(stored.modes[MODES.REC_LIST]?.main_cate)
          }
        }
      };
      next.activeMode = MODE_LABELS[next.activeMode] ? next.activeMode : MODES.FIND_DAREN;
      next.intervalSeconds = normalizeInterval(next.intervalSeconds);
      return next;
    }

    const migrated = createDefaultForm();
    migrated.inviteText = String(stored.inviteText || DEFAULT_INVITE_TEXT);
    migrated.phone = String(stored.phone || "");
    migrated.wechat = String(stored.wechat || "");
    migrated.rights = normalizeRights(stored.rights);
    migrated.commissionRatio = String(stored.commissionRatio || "");
    migrated.intervalSeconds = normalizeInterval(stored.intervalSeconds || stored.interval);
    migrated.manualProductIdsText = String(stored.productIds || "");
    migrated.legacyCategoryIdsText = String(stored.categoryIds || "");
    migrated.selectedProducts = parseIdList(stored.productIds).slice(0, MAX_INVITE_PRODUCTS).map((id) => ({
      product_id: id,
      product_name: `商品 ${id}`,
      author_sample_status: 1,
      customCommissionRatio: ""
    }));
    migrated.modes[MODES.FIND_DAREN].query = String(stored.keyword || "");
    migrated.modes[MODES.FIND_DAREN].type = Number(stored.contentType || 1);
    return migrated;
  }

  async function readAuthState() {
    const values = await chrome.storage.local.get([AUTH_KEY]).catch(() => ({}));
    return values[AUTH_KEY] || null;
  }

  async function readIntervalState(fallback) {
    const values = await chrome.storage.local.get([INTERVAL_KEY]).catch(() => ({}));
    return normalizeInterval(values[INTERVAL_KEY] || fallback || 5);
  }

  function isAuthActive(auth) {
    if (!auth || typeof auth !== "object") return false;
    const loggedIn = auth.loggedIn !== false;
    const active = Boolean(auth.active || auth.entitlement?.active || auth.account?.active);
    return loggedIn && active;
  }

  function normalizeInterval(value) {
    const number = Number(value || 5);
    return INTERVAL_OPTIONS.reduce((best, item) => (
      Math.abs(item - number) < Math.abs(best - number) ? item : best
    ), 5);
  }

  function shouldRetryBatchAsSingle(results) {
    const list = Array.isArray(results) ? results : [];
    return list.length > 1 && list.every((item) => (
      item?.type === "error" && shouldDowngrade(item?.text) && !isParameterError(item?.text)
    ));
  }

  function isParameterError(error) {
    const message = String(error?.message || error || "");
    return /参数错误|参数不合法|参数异常|invalid\s*param|invalid\s*parameter|missing\s*param/i.test(message);
  }

  function shouldDowngrade(error) {
    const message = String(error?.message || error || "");
    return isParameterError(message) || /请求过于频繁|邀约过于频繁|需要滑动滑块|Bdturing|风控|当前环境存在风险|稍后再试/i.test(message);
  }

  function normalizeDouDianMessage(message) {
    const text = String(message || "").trim();
    if (/Bdturing|滑块|captcha/i.test(text)) return "抖店需要滑块验证，请先在页面完成验证后再重试。";
    if (/登录信息已失效|账号未登录|用户未登录/i.test(text)) return "抖店登录已失效，请重新登录抖店后再试。";
    return text || "抖店请求失败。";
  }

  function cleanObject(value) {
    if (Array.isArray(value)) return value.map(cleanObject).filter((item) => item !== undefined);
    if (!value || typeof value !== "object") return value;
    const result = {};
    for (const [key, item] of Object.entries(value)) {
      if (item === undefined || item === null || item === "") continue;
      if (Array.isArray(item) && item.length === 0) continue;
      const next = cleanObject(item);
      if (next !== undefined) result[key] = next;
    }
    return result;
  }

  function buildEventParam() {
    return {
      client_form: "pc",
      web_did: "",
      seraph_did: "",
      x_pigeon_did: ""
    };
  }

  function parseIdList(value) {
    return String(value || "")
      .split(/[\s,，、\n\r]+/)
      .map((item) => item.trim())
      .filter(Boolean);
  }

  function parseTextList(value) {
    return String(value || "")
      .split(/[\s,，、\n\r]+/)
      .map((item) => item.trim())
      .filter(Boolean);
  }

  function formatNumber(value) {
    const number = Number(value || 0);
    if (!number) return "-";
    if (number >= 100000000) return `${(number / 100000000).toFixed(1)}亿`;
    if (number >= 10000) return `${(number / 10000).toFixed(1)}万`;
    return number.toLocaleString();
  }

  function isDarenSquarePage() {
    return location.hostname === "buyin.jinritemai.com" && location.pathname.startsWith(DAREN_SQUARE_PATH);
  }

  function showError(error) {
    const message = error?.message || String(error || "执行失败");
    syncStatus(message);
    toast(message);
    state.loading = false;
    state.sending = false;
    state.stopRequested = false;
    syncAll();
  }

  function toast(message) {
    const text = String(message || "").trim();
    if (!text) return;

    let node = document.getElementById(IDS.toast);
    if (!node) {
      node = document.createElement("div");
      node.id = IDS.toast;
      node.className = "mmwInviteToast";
      document.body.appendChild(node);
    }

    node.textContent = text;
    node.classList.add("is-open");
    window.clearTimeout(state.toastTimer);
    state.toastTimer = window.setTimeout(() => node?.classList.remove("is-open"), 2800);
  }

  function escapeHtml(value) {
    return String(value ?? "")
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#39;");
  }

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

  function normalizePlainObject(value) {
    return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : {};
  }

  function normalizeTalentColumns(value) {
    const source = normalizePlainObject(value);
    return Object.fromEntries(
      TALENT_TABLE_COLUMNS.map((column) => [column.key, source[column.key] !== false])
    );
  }

  function normalizeStringArray(value) {
    return Array.isArray(value) ? value.map((item) => String(item || "").trim()).filter(Boolean) : [];
  }

  function cloneJson(value) {
    return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
  }

  function delay(ms) {
    return new Promise((resolve) => window.setTimeout(resolve, ms));
  }

  function onReady(callback) {
    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", callback, { once: true });
    } else {
      callback();
    }
  }
})();
