import { COMMON_NOUNS } from "../hybrid/common-nouns.js";
const BRAND_TLD_RE = /\.(?:co\.uk|shop|store|deals|sale|boutique|fashion|com\.au|co\.nz)$/i;
const DEV_TERM_COLLISION_LEXICON = /* @__PURE__ */ new Set([
  "usestate",
  "useeffect",
  "usememo",
  "usereducer",
  "usecallback",
  "useref",
  "usecontext",
  "usestore",
  "next",
  "core",
  "apple",
  "mint",
  // these are also in the domain-collision path
  "redux",
  "mobx",
  "jotai",
  "zustand",
  "webpack",
  "babel",
  "rollup",
  "vite",
  "prisma",
  "drizzle",
  "kysely",
  "docker",
  "kubernetes",
  "helm"
]);
function hostOf(url) {
  try {
    return new URL(url).hostname.toLowerCase();
  } catch {
    return void 0;
  }
}
function looksBrandy(host) {
  return BRAND_TLD_RE.test(host);
}
function isBrandCollisionProne(query) {
  const tokens = query.trim().split(/\s+/).filter(Boolean);
  if (tokens.length === 0 || tokens.length > 2) return false;
  return tokens.every((t) => COMMON_NOUNS.has(t.toLowerCase()));
}
function suggestRewrites(query) {
  const q = query.trim();
  const lower = q.toLowerCase();
  if (lower === "next") {
    return ["Next.js framework", "next-router library", 'JavaScript "next" framework'];
  }
  if (lower === "core") {
    return [".NET Core", "wigolo core search", '"core" library'];
  }
  if (lower === "apple") {
    return ["Apple Inc.", "apple programming language", "apple fruit"];
  }
  if (lower === "mint") {
    return ["Linux Mint OS", "mint.com finance", "mint programming"];
  }
  return [
    `${q} framework`,
    `${q} programming`,
    `"${q}" library documentation`
  ];
}
function detectBrandCollision(query, topUrls) {
  if (!isBrandCollisionProne(query)) return null;
  const top3 = topUrls.slice(0, 3);
  const brandy = [];
  for (const url of top3) {
    const host = hostOf(url);
    if (!host) continue;
    if (looksBrandy(host)) brandy.push(host);
  }
  if (brandy.length === 0) return null;
  return {
    detected: true,
    reason: `query "${query.trim()}" is a common noun that also matches brand domain(s) in the top-3`,
    brand_domains_in_top_3: brandy,
    suggested_rewrites: suggestRewrites(query)
  };
}
function withinEditDistance(a, b, maxDist) {
  if (Math.abs(a.length - b.length) > maxDist) return false;
  const m = a.length;
  const n = b.length;
  let prev = new Array(n + 1);
  let curr = new Array(n + 1);
  for (let j = 0; j <= n; j++) prev[j] = j;
  for (let i = 1; i <= m; i++) {
    curr[0] = i;
    let rowMin = curr[0];
    for (let j = 1; j <= n; j++) {
      const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
      curr[j] = Math.min(
        prev[j] + 1,
        curr[j - 1] + 1,
        prev[j - 1] + cost
      );
      if (curr[j] < rowMin) rowMin = curr[j];
    }
    if (rowMin > maxDist) return false;
    [prev, curr] = [curr, prev];
  }
  return prev[n] <= maxDist;
}
function detectLexicalCollision(query) {
  const trimmed = query.trim();
  if (!trimmed) return null;
  const tokens = trimmed.split(/\s+/).filter(Boolean);
  if (tokens.length !== 1) return null;
  const candidate = tokens[0].toLowerCase().replace(/[^a-z0-9]/g, "");
  if (candidate.length < 4 || candidate.length > 24) return null;
  let matchedTerm = null;
  for (const term of DEV_TERM_COLLISION_LEXICON) {
    if (term === candidate) {
      matchedTerm = term;
      break;
    }
    const budget = Math.min(2, Math.floor(term.length / 8) + 1);
    if (withinEditDistance(candidate, term, budget)) {
      matchedTerm = term;
      break;
    }
  }
  if (!matchedTerm) return null;
  return {
    detected: true,
    reason: `query "${trimmed}" is lexically close to "${matchedTerm}" \u2014 a popular dev term; results may be drawn from the unrelated meaning space`,
    brand_domains_in_top_3: [],
    suggested_rewrites: [
      `${matchedTerm} React hook`,
      `"${matchedTerm}" documentation`,
      `${matchedTerm} api reference`
    ]
  };
}
export {
  detectBrandCollision,
  detectLexicalCollision
};
//# sourceMappingURL=brand-collision.js.map