import { detectAll } from "tinyld";
import { createLogger } from "../logger.js";
const MIN_DETECT_CHARS = 12;
const MIN_CONFIDENCE = 0.1;
const LATIN_LANGS = /* @__PURE__ */ new Set([
  "en",
  "es",
  "fr",
  "pt",
  "de",
  "it",
  "nl",
  "da",
  "sv",
  "no",
  "fi",
  "is",
  "pl",
  "cs",
  "sk",
  "hu",
  "ro",
  "hr",
  "sl",
  "lt",
  "lv",
  "et",
  "tr",
  "vi",
  "id",
  "ms",
  "tl",
  "sw",
  "af",
  "ca",
  "gl",
  "eu",
  "ga",
  "cy",
  "mt",
  "sq",
  "lb",
  "fo",
  "ber",
  "so",
  "ha",
  "yo",
  "ig",
  "zu",
  "xh",
  "st",
  "tn"
]);
const log = createLogger("language-filter");
function isValidUrl(u) {
  try {
    const parsed = new URL(u);
    return parsed.protocol === "http:" || parsed.protocol === "https:";
  } catch {
    return false;
  }
}
function detectLang(text) {
  const t = text?.trim() ?? "";
  if (t.length < MIN_DETECT_CHARS) return "und";
  try {
    const ranked = detectAll(t);
    const top = ranked[0];
    if (!top || top.accuracy < MIN_CONFIDENCE) return "und";
    return top.lang || "und";
  } catch {
    return "und";
  }
}
function filterByLanguage(results, opts) {
  const discarded = [];
  const warnings = [];
  const urlValid = [];
  for (const r of results) {
    if (!isValidUrl(r.url)) {
      discarded.push({ result: r, reason: "invalid_url" });
      continue;
    }
    urlValid.push(r);
  }
  if (urlValid.length === 0) return { results: [], discarded, warnings };
  const byEngine = /* @__PURE__ */ new Map();
  for (const r of urlValid) {
    const arr = byEngine.get(r.engine) ?? [];
    arr.push(r);
    byEngine.set(r.engine, arr);
  }
  const targetIsLatin = LATIN_LANGS.has(opts.target);
  const isMismatch = (lang) => {
    if (lang === opts.target || lang === "und") return false;
    if (targetIsLatin && LATIN_LANGS.has(lang)) return false;
    return true;
  };
  const kept = [];
  for (const [engine, batch] of byEngine) {
    let nonTarget = 0;
    const langs = batch.map((r) => detectLang(`${r.title} ${r.snippet}`));
    for (const l of langs) if (isMismatch(l)) nonTarget += 1;
    const ratio = nonTarget / batch.length;
    if (ratio > opts.dropThreshold) {
      warnings.push(
        `engine_language_mismatch: ${engine} returned ${Math.round(ratio * 100)}% non-${opts.target}; batch dropped`
      );
      for (const r of batch) discarded.push({ result: r, reason: "engine_batch_dropped" });
      log.warn("dropped engine batch for language mismatch", { engine, ratio });
      continue;
    }
    for (let i = 0; i < batch.length; i += 1) {
      if (isMismatch(langs[i])) {
        discarded.push({ result: batch[i], reason: "language_mismatch" });
      } else {
        kept.push(batch[i]);
      }
    }
  }
  return { results: kept, discarded, warnings };
}
function filterByLanguageWithFallback(results, opts) {
  if (results.length === 0) {
    return filterByLanguage(results, opts);
  }
  const filtered = filterByLanguage(results, opts);
  if (filtered.results.length > 0) return filtered;
  const perResult = filterByLanguage(results, { ...opts, dropThreshold: 1 });
  if (perResult.results.length > 0) {
    return {
      results: perResult.results,
      discarded: perResult.discarded,
      warnings: [
        ...filtered.warnings,
        `language_filter_relaxed: strict batch drop emptied results; falling back to per-result lang filter with target=${opts.target}.`
      ]
    };
  }
  const urlValid = results.filter((r) => isValidUrl(r.url));
  if (urlValid.length === 0) return filtered;
  return {
    results: urlValid,
    discarded: filtered.discarded.filter((d) => d.reason === "invalid_url"),
    warnings: [
      ...filtered.warnings,
      `language_filter_relaxed: every engine batch failed the language check for target=${opts.target}; returning ${urlValid.length} unfiltered result(s) to avoid an empty response. Pass an explicit language= or refine the query if results look wrong.`
    ]
  };
}
export {
  filterByLanguage,
  filterByLanguageWithFallback
};
//# sourceMappingURL=language-filter.js.map