import { normalizeUrl } from "../../cache/store.js";
import { normalizeResultUrl } from "../url-unwrap.js";
import {
  buildRankMap,
  reciprocalRankFusion,
  sortByRRFScore
} from "../rrf.js";
const RRF_K = 60;
function canonicalKey(url) {
  const unwrapped = normalizeResultUrl(url);
  try {
    return normalizeUrl(unwrapped);
  } catch {
    return unwrapped;
  }
}
function preferred(existing, candidate) {
  const existingHasContent = typeof existing.markdown_content === "string" && existing.markdown_content.length > 0;
  const candidateHasContent = typeof candidate.markdown_content === "string" && candidate.markdown_content.length > 0;
  if (existingHasContent !== candidateHasContent) {
    return existingHasContent ? existing : candidate;
  }
  return candidate.relevance_score > existing.relevance_score ? candidate : existing;
}
function collectKeyedResults(source, byKey) {
  const keys = [];
  for (const r of source.results) {
    const key = canonicalKey(r.url);
    keys.push(key);
    const existing = byKey.get(key);
    byKey.set(key, existing ? preferred(existing, r) : r);
  }
  return keys;
}
function mergeResults(core, searxng, options = {}) {
  const byKey = /* @__PURE__ */ new Map();
  const coreKeys = collectKeyedResults(core, byKey);
  const searxngKeys = collectKeyedResults(searxng, byKey);
  const lists = [];
  if (coreKeys.length > 0) lists.push(buildRankMap(coreKeys));
  if (searxngKeys.length > 0) lists.push(buildRankMap(searxngKeys));
  const fused = reciprocalRankFusion(lists, RRF_K);
  const sorted = sortByRRFScore(fused);
  const maxScore = sorted[0]?.[1] ?? 0;
  const ordered = [];
  for (const [key, score] of sorted) {
    const base = byKey.get(key);
    if (!base) continue;
    ordered.push({
      ...base,
      relevance_score: maxScore > 0 ? score / maxScore : base.relevance_score
    });
  }
  const cap = typeof options.maxResults === "number" && options.maxResults >= 0 ? options.maxResults : ordered.length;
  const results = ordered.slice(0, cap);
  const enginesSet = /* @__PURE__ */ new Set([
    ...core.engines_used,
    ...searxng.engines_used
  ]);
  const merged = {
    results,
    engines_used: [...enginesSet]
  };
  if (core.engine_outcomes || searxng.engine_outcomes) {
    merged.engine_outcomes = [
      ...core.engine_outcomes ?? [],
      ...searxng.engine_outcomes ?? []
    ];
  }
  return merged;
}
export {
  mergeResults
};
//# sourceMappingURL=merge.js.map