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

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

function isOfferLinkHref(href) {
  const value = cleanText(href);
  return (
    value.includes("detail.m.1688.com/page/index.html")
    || value.includes("detail.1688.com/offer/")
    || /offerId=\d+/i.test(value)
  );
}

function isMerchantLinkHref(href) {
  const value = cleanText(href);
  return (
    value.includes(".1688.com/")
    && !/offerId=\d+/i.test(value)
    && !value.includes("detail.1688.com/offer/")
    && !value.includes("detail.m.1688.com/page/index.html")
    && !value.includes("def_cbu_web_im")
    && !value.includes("similar_search")
    && !value.includes("fcaReport")
    && !value.includes("auth/")
  );
}

function extractOfferId(href) {
  const value = cleanText(href);
  const mobileMatch = value.match(/[?&]offerId=(\d+)/i);
  if (mobileMatch?.[1]) {
    return mobileMatch[1];
  }

  const pcMatch = value.match(/\/offer\/(\d+)\.html/i);
  return pcMatch?.[1] ?? "";
}

function normalizeOfferUrl(href) {
  const value = cleanText(href);
  const offerId = extractOfferId(value);
  return offerId ? `https://detail.1688.com/offer/${offerId}.html` : value;
}

function normalizeMerchantName(value) {
  return cleanText(value)
    .replace(/入驻\d+年/g, " ")
    .replace(/回头率\d+(?:\.\d+)?%/g, " ")
    .replace(/店铺服务分\s*\d+(?:\.\d+)?分/g, " ")
    .replace(/准时发货率\s*\d+(?:\.\d+)?%/g, " ")
    .replace(/店铺好评率\s*\d+(?:\.\d+)?%/g, " ")
    .replace(/主营[:：][^\s]+/g, " ")
    .replace(/旺旺在线/g, " ")
    .replace(/官方旺旺/g, " ")
    .replace(/立即沟通/g, " ");
}

export function looksLikeMerchantName(value) {
  const text = cleanText(value);
  if (!text || text.length < 4) {
    return false;
  }

  return (
    /(?:有限责任公司|股份有限公司|有限公司|商行|经营部|经销处|批发部|门市部|办事处|旗舰店|专营店|直营店|直营网店|店铺|官方店|专卖店|合作社|厂)$/u.test(text)
    || /(?:省|市|县|区|镇).{0,18}(?:公司|商行|经营部|厂)$/u.test(text)
  );
}

const TITLE_NOISE_PATTERNS = [
  /^找相似/g,
  /旺旺在线/g,
  /官方旺旺/g,
  /立即沟通/g,
  /点(?:击|此)(?:可直接|可以直接|可|可以)?(?:和|与)(?:卖家|商家)(?:交流|沟通|联系)[\s\S]*$/g,
  /(?:还|并且)?支持语音视频哦。?/g,
  /(?:选好|选中)?的?宝贝[，,。.]?/g,
  /(?:或|或者)?(?:到|至)?互动购(?:网站|网页)?体验[，,。.]?/g,
  /综合服务验厂报告/g,
  /综合服务/g,
  /验厂报告/g,
  /采购咨询\d+(?:\.\d+)?/g,
  /退换体验\d+(?:\.\d+)?/g,
  /品质体验\d+(?:\.\d+)?/g,
  /纠纷解决\d+(?:\.\d+)?/g,
  /物流时效\d+(?:\.\d+)?/g,
  /回头率\d+(?:\.\d+)?%/g,
  /退货包运费/g,
  /先采后付/g,
  /官方物流/g,
  /首单减\d+[^\s]*/g,
  /最高返\d+[^\s]*/g,
  /商机组货[:：][^\s]+/g,
  /分享再减[^¥]*/g,
  /元宝可抵[^¥]*/g,
  /¥\s*\d[\d.,]*(?:\s*[~至-]\s*\d[\d.,]*)?(?:\s*\/\s*[^\s]+)?[\s\S]*$/g,
  /\d+\+?件[\s\S]*$/g,
  /满\d+[^\s]*[\s\S]*$/g,
  /入驻\d+年[\s\S]*$/g,
  /店铺服务分\s*\d+(?:\.\d+)?分[\s\S]*$/g,
  /准时发货率\s*\d+(?:\.\d+)?%[\s\S]*$/g,
  /店铺好评率\s*\d+(?:\.\d+)?%[\s\S]*$/g,
  /主营[:：][\s\S]*$/g,
  /(材料|型式|造型|品种|类型)[:：][\s\S]*$/g,
];

export function sanitizeSearchResultTitle(value, merchantName = "") {
  let text = cleanText(value);
  if (!text) {
    return "";
  }

  const normalizedMerchantName = normalizeMerchantName(merchantName);
  if (normalizedMerchantName) {
    text = cleanText(text.replace(new RegExp(escapeRegExp(normalizedMerchantName), "gu"), " "));
  }

  for (const pattern of TITLE_NOISE_PATTERNS) {
    text = text.replace(pattern, " ");
  }

  text = cleanText(text);
  if (!text || looksLikeMerchantName(text)) {
    return "";
  }

  return text;
}

export function looksLikeSearchResultTitle(value, merchantName = "") {
  const text = sanitizeSearchResultTitle(value, merchantName);
  return (
    text.length >= 8
    && !/^¥/.test(text)
    && !text.includes("找相似")
    && !looksLikeMerchantName(text)
    && !looksLikeGeneratedResourceTitle(text)
  );
}

export function looksLikeGeneratedResourceTitle(value) {
  const text = cleanText(value);
  if (!text) {
    return false;
  }

  if (/^(?:https?:)?\/\//i.test(text) || /^data:[a-z]+\/[a-z0-9.+-]+;base64,/i.test(text)) {
    return true;
  }

  const compact = text.replace(/\s+/g, "");
  if (compact.length < 16 || /[\u4e00-\u9fff]/u.test(compact)) {
    return false;
  }

  if (/[|]/.test(compact) && /^[A-Za-z0-9_|+=/-]+$/.test(compact)) {
    return true;
  }

  if (/^[A-Fa-f0-9]{24,}$/.test(compact)) {
    return true;
  }

  if (/^[A-Za-z0-9_-]{28,}$/.test(compact) && !/[.]/.test(compact)) {
    const letters = (compact.match(/[A-Za-z]/g) ?? []).length;
    const digits = (compact.match(/\d/g) ?? []).length;
    return letters > 0 && digits > 0;
  }

  return false;
}

function isVisibleElement(element, visibleOnly) {
  if (!visibleOnly || !element) {
    return true;
  }

  const ownerWindow = element.ownerDocument?.defaultView;
  const style = ownerWindow?.getComputedStyle?.(element);
  if (style && (style.display === "none" || style.visibility === "hidden")) {
    return false;
  }

  const rect = typeof element.getBoundingClientRect === "function"
    ? element.getBoundingClientRect()
    : null;

  return !rect || rect.width > 0 || rect.height > 0;
}

function collectAnchors(container, predicate, visibleOnly) {
  return Array.from(container.querySelectorAll("a[href]"))
    .filter((anchor) => predicate(anchor.href) && isVisibleElement(anchor, visibleOnly));
}

function collectHighlightTexts(container, visibleOnly) {
  const selectors = [
    "em",
    "strong",
    "font[color]",
    '[class*="highlight"]',
    '[class*="Highlight"]',
    '[class*="red"]',
    '[class*="Red"]',
    '[style*="color"]',
  ];
  const seen = new Set();
  const output = [];

  for (const selector of selectors) {
    for (const node of Array.from(container.querySelectorAll(selector))) {
      if (!isVisibleElement(node, visibleOnly)) {
        continue;
      }

      const text = cleanText(node.textContent ?? "");
      if (!text) {
        continue;
      }

      const key = text.toLowerCase();
      if (seen.has(key)) {
        continue;
      }

      seen.add(key);
      output.push(text);
    }
  }

  return output;
}

function buildContainerScore(container, visibleOnly) {
  if (!container || !isVisibleElement(container, visibleOnly)) {
    return Number.NEGATIVE_INFINITY;
  }

  const text = cleanText(container.textContent);
  const anchors = Array.from(container.querySelectorAll("a[href]"));
  const offerLinks = anchors.filter((anchor) => isOfferLinkHref(anchor.href));
  const merchantLinks = anchors.filter((anchor) => isMerchantLinkHref(anchor.href));
  let score = 0;

  if (text.length >= 12) score += 1;
  if (text.length <= 500) score += 1;
  if (container.querySelector("img")) score += 1;
  if (offerLinks.length >= 1) score += 1;
  if (merchantLinks.length >= 1) score += 2;
  if (anchors.length <= 12) score += 1;

  return score;
}

function findResultContainer(offerLink, visibleOnly) {
  let current = offerLink;
  let bestContainer = offerLink.parentElement ?? offerLink;
  let bestScore = Number.NEGATIVE_INFINITY;

  for (let depth = 0; current && depth < 8; depth += 1) {
    const score = buildContainerScore(current, visibleOnly);
    if (score > bestScore) {
      bestScore = score;
      bestContainer = current;
    }

    if (score >= 5) {
      break;
    }

    current = current.parentElement;
  }

  return bestContainer;
}

function pickMerchantName(container, offerLink, visibleOnly) {
  const directSelectors = [
    '[class*="shopName"]',
    '[class*="shop-company-name"]',
    '[class*="companyName"]',
    '[class*="company-name"]',
    '[class*="offerShopRow"]',
    '[class*="shopInfo"]',
  ];

  for (const selector of directSelectors) {
    const candidate = container.querySelector(selector);
    const text = normalizeMerchantName(candidate?.textContent ?? "");
    if (text && looksLikeMerchantName(text)) {
      return text;
    }
  }

  const merchantAnchor = collectAnchors(container, isMerchantLinkHref, visibleOnly)
    .find((anchor) => anchor !== offerLink);
  return normalizeMerchantName(merchantAnchor?.textContent ?? "");
}

function pushCandidate(candidates, seen, rawValue, merchantName) {
  const candidate = sanitizeSearchResultTitle(rawValue, merchantName);
  if (!candidate) {
    return;
  }

  const key = candidate.toLowerCase();
  if (seen.has(key)) {
    return;
  }

  seen.add(key);
  candidates.push(candidate);
}

function pickTitleFromContainer(container, merchantName, visibleOnly) {
  const candidates = [];
  const seen = new Set();
  const preferredSelectors = [
    '[class*="title"]',
    '[class*="Title"]',
    '[class*="subject"]',
    '[class*="Subject"]',
    '[class*="desc"]',
    '[class*="Desc"]',
    'h1',
    'h2',
    'h3',
    '[title]',
  ];

  for (const selector of preferredSelectors) {
    for (const node of Array.from(container.querySelectorAll(selector))) {
      if (!isVisibleElement(node, visibleOnly)) {
        continue;
      }

      const ownerAnchor = node.closest("a[href]");
      if (ownerAnchor && isMerchantLinkHref(ownerAnchor.href)) {
        continue;
      }

      pushCandidate(candidates, seen, node.getAttribute?.("title") ?? node.textContent ?? "", merchantName);
    }
  }

  for (const offerAnchor of collectAnchors(container, isOfferLinkHref, visibleOnly)) {
    for (const node of Array.from(offerAnchor.querySelectorAll("*"))) {
      pushCandidate(candidates, seen, node.textContent ?? "", merchantName);
    }

    pushCandidate(candidates, seen, offerAnchor.getAttribute("title") ?? offerAnchor.textContent ?? "", merchantName);
  }

  const image = container.querySelector("img");
  pushCandidate(candidates, seen, image?.getAttribute("alt") ?? "", merchantName);
  pushCandidate(candidates, seen, image?.getAttribute("title") ?? "", merchantName);
  pushCandidate(candidates, seen, container.textContent ?? "", merchantName);

  return candidates.find((candidate) => looksLikeSearchResultTitle(candidate, merchantName)) ?? candidates[0] ?? "";
}

function buildRawResult(container, offerLink, visibleOnly) {
  const merchantAnchor = collectAnchors(container, isMerchantLinkHref, visibleOnly)
    .find((anchor) => anchor !== offerLink);
  const merchantName = pickMerchantName(container, offerLink, visibleOnly);
  const image = offerLink.querySelector("img") ?? container.querySelector("img");

  return {
    title: pickTitleFromContainer(container, merchantName, visibleOnly),
    rawCardText: cleanText(container.textContent ?? ""),
    highlightTexts: collectHighlightTexts(container, visibleOnly),
    offerUrl: normalizeOfferUrl(offerLink.href),
    imageUrl:
      image?.getAttribute("src")
      ?? image?.getAttribute("data-src")
      ?? image?.getAttribute("data-lazy-src")
      ?? "",
    merchantName,
    merchantUrl: merchantAnchor?.href ?? "",
  };
}

export function extractSearchResultCandidatesFromDocument(documentNode, take, options = {}) {
  function cleanTextInner(value) {
    return String(value ?? "")
      .replace(/\u00a0/g, " ")
      .replace(/\s+/g, " ")
      .trim();
  }

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

  function isOfferLinkHrefInner(href) {
    const value = cleanTextInner(href);
    return (
      value.includes("detail.m.1688.com/page/index.html")
      || value.includes("detail.1688.com/offer/")
      || /offerId=\d+/i.test(value)
    );
  }

  function isMerchantLinkHrefInner(href) {
    const value = cleanTextInner(href);
    return (
      value.includes(".1688.com/")
      && !/offerId=\d+/i.test(value)
      && !value.includes("detail.1688.com/offer/")
      && !value.includes("detail.m.1688.com/page/index.html")
      && !value.includes("def_cbu_web_im")
      && !value.includes("similar_search")
      && !value.includes("fcaReport")
      && !value.includes("auth/")
    );
  }

  function extractOfferIdInner(href) {
    const value = cleanTextInner(href);
    const mobileMatch = value.match(/[?&]offerId=(\d+)/i);
    if (mobileMatch?.[1]) {
      return mobileMatch[1];
    }

    const pcMatch = value.match(/\/offer\/(\d+)\.html/i);
    return pcMatch?.[1] ?? "";
  }

  function normalizeOfferUrlInner(href) {
    const value = cleanTextInner(href);
    const offerId = extractOfferIdInner(value);
    return offerId ? `https://detail.1688.com/offer/${offerId}.html` : value;
  }

  function normalizeMerchantNameInner(value) {
    return cleanTextInner(value)
      .replace(/入驻\d+年/g, " ")
      .replace(/回头率\d+(?:\.\d+)?%/g, " ")
      .replace(/店铺服务分\s*\d+(?:\.\d+)?分/g, " ")
      .replace(/准时发货率\s*\d+(?:\.\d+)?%/g, " ")
      .replace(/店铺好评率\s*\d+(?:\.\d+)?%/g, " ")
      .replace(/主营[:：][^\s]+/g, " ")
      .replace(/旺旺在线/g, " ")
      .replace(/官方旺旺/g, " ")
      .replace(/立即沟通/g, " ");
  }

  function looksLikeMerchantNameInner(value) {
    const text = cleanTextInner(value);
    if (!text || text.length < 4) {
      return false;
    }

    return (
      /(?:有限责任公司|股份有限公司|有限公司|商行|经营部|经销处|批发部|门市部|办事处|旗舰店|专营店|直营店|直营网店|店铺|官方店|专卖店|合作社|厂)$/u.test(text)
      || /(?:省|市|县|区|镇).{0,18}(?:公司|商行|经营部|厂)$/u.test(text)
    );
  }

  const titleNoisePatterns = [
    /^找相似/g,
    /旺旺在线/g,
    /官方旺旺/g,
    /立即沟通/g,
    /点(?:击|此)(?:可直接|可以直接|可|可以)?(?:和|与)(?:卖家|商家)(?:交流|沟通|联系)[\s\S]*$/g,
    /(?:还|并且)?支持语音视频哦。?/g,
    /(?:选好|选中)?的?宝贝[，,。.]?/g,
    /(?:或|或者)?(?:到|至)?互动购(?:网站|网页)?体验[，,。.]?/g,
    /综合服务验厂报告/g,
    /综合服务/g,
    /验厂报告/g,
    /采购咨询\d+(?:\.\d+)?/g,
    /退换体验\d+(?:\.\d+)?/g,
    /品质体验\d+(?:\.\d+)?/g,
    /纠纷解决\d+(?:\.\d+)?/g,
    /物流时效\d+(?:\.\d+)?/g,
    /回头率\d+(?:\.\d+)?%/g,
    /退货包运费/g,
    /先采后付/g,
    /官方物流/g,
    /首单减\d+[^\s]*/g,
    /最高返\d+[^\s]*/g,
    /商机组货[:：][^\s]+/g,
    /分享再减[^¥]*/g,
    /元宝可抵[^¥]*/g,
    /¥\s*\d[\d.,]*(?:\s*[~至-]\s*\d[\d.,]*)?(?:\s*\/\s*[^\s]+)?[\s\S]*$/g,
    /\d+\+?件[\s\S]*$/g,
    /满\d+[^\s]*[\s\S]*$/g,
    /入驻\d+年[\s\S]*$/g,
    /店铺服务分\s*\d+(?:\.\d+)?分[\s\S]*$/g,
    /准时发货率\s*\d+(?:\.\d+)?%[\s\S]*$/g,
    /店铺好评率\s*\d+(?:\.\d+)?%[\s\S]*$/g,
    /主营[:：][\s\S]*$/g,
    /(材料|型式|造型|品种|类型)[:：][\s\S]*$/g,
  ];

  function sanitizeSearchResultTitleInner(value, merchantName = "") {
    let text = cleanTextInner(value);
    if (!text) {
      return "";
    }

    const normalizedMerchantName = normalizeMerchantNameInner(merchantName);
    if (normalizedMerchantName) {
      text = cleanTextInner(text.replace(new RegExp(escapeRegExpInner(normalizedMerchantName), "gu"), " "));
    }

    for (const pattern of titleNoisePatterns) {
      text = text.replace(pattern, " ");
    }

    text = cleanTextInner(text);
    if (!text || looksLikeMerchantNameInner(text)) {
      return "";
    }

    return text;
  }

  function looksLikeSearchResultTitleInner(value, merchantName = "") {
    const text = sanitizeSearchResultTitleInner(value, merchantName);
    return (
      text.length >= 8
      && !/^¥/.test(text)
      && !text.includes("找相似")
      && !looksLikeMerchantNameInner(text)
    );
  }

  function isVisibleElementInner(element) {
    if (!visibleOnly || !element) {
      return true;
    }

    const ownerWindow = element.ownerDocument?.defaultView;
    const style = ownerWindow?.getComputedStyle?.(element);
    if (style && (style.display === "none" || style.visibility === "hidden")) {
      return false;
    }

    const rect = typeof element.getBoundingClientRect === "function"
      ? element.getBoundingClientRect()
      : null;

    return !rect || rect.width > 0 || rect.height > 0;
  }

  function collectAnchorsInner(container, predicate) {
    return Array.from(container.querySelectorAll("a[href]"))
      .filter((anchor) => predicate(anchor.href) && isVisibleElementInner(anchor));
  }

  function collectHighlightTextsInner(container) {
    const selectors = [
      "em",
      "strong",
      "font[color]",
      '[class*="highlight"]',
      '[class*="Highlight"]',
      '[class*="red"]',
      '[class*="Red"]',
      '[style*="color"]',
    ];
    const seen = new Set();
    const output = [];

    for (const selector of selectors) {
      for (const node of Array.from(container.querySelectorAll(selector))) {
        if (!isVisibleElementInner(node)) {
          continue;
        }

        const text = cleanTextInner(node.textContent ?? "");
        if (!text) {
          continue;
        }

        const key = text.toLowerCase();
        if (seen.has(key)) {
          continue;
        }

        seen.add(key);
        output.push(text);
      }
    }

    return output;
  }

  function buildContainerScoreInner(container) {
    if (!container || !isVisibleElementInner(container)) {
      return Number.NEGATIVE_INFINITY;
    }

    const text = cleanTextInner(container.textContent);
    const anchors = Array.from(container.querySelectorAll("a[href]"));
    const offerLinks = anchors.filter((anchor) => isOfferLinkHrefInner(anchor.href));
    const merchantLinks = anchors.filter((anchor) => isMerchantLinkHrefInner(anchor.href));
    let score = 0;

    if (text.length >= 12) score += 1;
    if (text.length <= 500) score += 1;
    if (container.querySelector("img")) score += 1;
    if (offerLinks.length >= 1) score += 1;
    if (merchantLinks.length >= 1) score += 2;
    if (anchors.length <= 12) score += 1;

    return score;
  }

  function findResultContainerInner(offerLink) {
    let current = offerLink;
    let bestContainer = offerLink.parentElement ?? offerLink;
    let bestScore = Number.NEGATIVE_INFINITY;

    for (let depth = 0; current && depth < 8; depth += 1) {
      const score = buildContainerScoreInner(current);
      if (score > bestScore) {
        bestScore = score;
        bestContainer = current;
      }

      if (score >= 5) {
        break;
      }

      current = current.parentElement;
    }

    return bestContainer;
  }

  function pickMerchantNameInner(container, offerLink) {
    const directSelectors = [
      '[class*="shopName"]',
      '[class*="shop-company-name"]',
      '[class*="companyName"]',
      '[class*="company-name"]',
      '[class*="offerShopRow"]',
      '[class*="shopInfo"]',
    ];

    for (const selector of directSelectors) {
      const candidate = container.querySelector(selector);
      const text = normalizeMerchantNameInner(candidate?.textContent ?? "");
      if (text && looksLikeMerchantNameInner(text)) {
        return text;
      }
    }

    const merchantAnchor = collectAnchorsInner(container, isMerchantLinkHrefInner)
      .find((anchor) => anchor !== offerLink);
    return normalizeMerchantNameInner(merchantAnchor?.textContent ?? "");
  }

  function pushCandidateInner(candidates, seen, rawValue, merchantName) {
    const candidate = sanitizeSearchResultTitleInner(rawValue, merchantName);
    if (!candidate) {
      return;
    }

    const key = candidate.toLowerCase();
    if (seen.has(key)) {
      return;
    }

    seen.add(key);
    candidates.push(candidate);
  }

  function pickTitleFromContainerInner(container, merchantName) {
    const candidates = [];
    const seen = new Set();
    const preferredSelectors = [
      '[class*="title"]',
      '[class*="Title"]',
      '[class*="subject"]',
      '[class*="Subject"]',
      '[class*="desc"]',
      '[class*="Desc"]',
      'h1',
      'h2',
      'h3',
      '[title]',
    ];

    for (const selector of preferredSelectors) {
      for (const node of Array.from(container.querySelectorAll(selector))) {
        if (!isVisibleElementInner(node)) {
          continue;
        }

        const ownerAnchor = node.closest("a[href]");
        if (ownerAnchor && isMerchantLinkHrefInner(ownerAnchor.href)) {
          continue;
        }

        pushCandidateInner(candidates, seen, node.getAttribute?.("title") ?? node.textContent ?? "", merchantName);
      }
    }

    for (const offerAnchor of collectAnchorsInner(container, isOfferLinkHrefInner)) {
      for (const node of Array.from(offerAnchor.querySelectorAll("*"))) {
        pushCandidateInner(candidates, seen, node.textContent ?? "", merchantName);
      }

      pushCandidateInner(candidates, seen, offerAnchor.getAttribute("title") ?? offerAnchor.textContent ?? "", merchantName);
    }

    const image = container.querySelector("img");
    pushCandidateInner(candidates, seen, image?.getAttribute("alt") ?? "", merchantName);
    pushCandidateInner(candidates, seen, image?.getAttribute("title") ?? "", merchantName);
    pushCandidateInner(candidates, seen, container.textContent ?? "", merchantName);

    return candidates.find((candidate) => looksLikeSearchResultTitleInner(candidate, merchantName)) ?? candidates[0] ?? "";
  }

  function buildRawResultInner(container, offerLink) {
    const merchantAnchor = collectAnchorsInner(container, isMerchantLinkHrefInner)
      .find((anchor) => anchor !== offerLink);
    const merchantName = pickMerchantNameInner(container, offerLink);
    const image = offerLink.querySelector("img") ?? container.querySelector("img");

    return {
      title: pickTitleFromContainerInner(container, merchantName),
      rawCardText: cleanTextInner(container.textContent ?? ""),
      highlightTexts: collectHighlightTextsInner(container),
      offerUrl: normalizeOfferUrlInner(offerLink.href),
      imageUrl:
        image?.getAttribute("src")
        ?? image?.getAttribute("data-src")
        ?? image?.getAttribute("data-lazy-src")
        ?? "",
      merchantName,
      merchantUrl: merchantAnchor?.href ?? "",
    };
  }

  const visibleOnly = Boolean(options.visibleOnly);
  const limit = Number.isInteger(take) && take > 0 ? take : 10;
  const cardNodes = Array.from(documentNode.querySelectorAll('[class*="searchOfferWrapper"][class*="searchOfferItem"]'));
  const cardItems = [];
  const seenCardOfferKeys = new Set();

  for (const card of cardNodes) {
    if (!isVisibleElementInner(card)) {
      continue;
    }

    const offerLink = collectAnchorsInner(card, isOfferLinkHrefInner)[0] ?? null;
    if (!offerLink) {
      continue;
    }

    const offerKey = extractOfferIdInner(offerLink.href) || normalizeOfferUrlInner(offerLink.href);
    if (!offerKey || seenCardOfferKeys.has(offerKey)) {
      continue;
    }

    seenCardOfferKeys.add(offerKey);
    const rawResult = buildRawResultInner(card, offerLink);
    if (!rawResult.offerUrl) {
      continue;
    }

    cardItems.push(rawResult);
    if (cardItems.length >= limit) {
      break;
    }
  }

  if (cardItems.length > 0) {
    return cardItems;
  }

  const offerLinks = Array.from(documentNode.querySelectorAll("a[href]"))
    .filter((anchor) => isOfferLinkHrefInner(anchor.href) && isVisibleElementInner(anchor));
  const seenOfferKeys = new Set();
  const items = [];

  for (const offerLink of offerLinks) {
    const offerKey = extractOfferIdInner(offerLink.href) || normalizeOfferUrlInner(offerLink.href);
    if (!offerKey || seenOfferKeys.has(offerKey)) {
      continue;
    }

    seenOfferKeys.add(offerKey);
    const container = findResultContainerInner(offerLink);
    const rawResult = buildRawResultInner(container, offerLink);
    if (!rawResult.offerUrl) {
      continue;
    }

    items.push(rawResult);
    if (items.length >= limit) {
      break;
    }
  }

  return items;
}
