import { parseHTML } from "linkedom";
import { defuddleExtract } from "../defuddle.js";
import { readabilityExtract } from "../readability.js";
import { htmlToMarkdown } from "../markdown.js";
import { stripBoilerplateDom } from "../boilerplate.js";
import { createLogger } from "../../logger.js";
import { classifyContent } from "./classifier.js";
import { extractRecipe } from "./recipe.js";
import { extractProduct } from "./product.js";
import { extractNews } from "./news.js";
import { getSiteExtractors } from "./site-extractors.js";
import { detectAntiBotBlock as detectRedditBlock } from "../site-extractors/reddit.js";
import { detectAntiBotBlock as detectAmazonBlock } from "../site-extractors/amazon.js";
const log = createLogger("extract");
async function routedExtract(input) {
  const { html, url } = input;
  const cleanedHtml = input.cleanedHtml ?? cleanHtml(html, url);
  const siteHit = trySiteExtractors(cleanedHtml, url, html);
  if (siteHit) return siteHit;
  const blocked = detectSiteBlock(url, html);
  const type = classifyContent(url, html);
  log.debug("classified content", { url, type, blocked });
  const result = await (async () => {
    switch (type) {
      case "recipe":
        return await extractRecipe(cleanedHtml, url) ?? await fallbackChain(cleanedHtml, url);
      case "product":
        return await extractProduct(cleanedHtml, url) ?? await fallbackChain(cleanedHtml, url);
      case "news":
        return await extractNews(cleanedHtml, url) ?? await fallbackChain(cleanedHtml, url);
      case "code":
      case "docs":
      case "generic":
      default:
        return fallbackChain(cleanedHtml, url, type);
    }
  })();
  if (blocked) {
    result.site_data_blocked = blocked;
  }
  return result;
}
function detectSiteBlock(url, html) {
  let host = "";
  try {
    host = new URL(url).hostname.toLowerCase();
  } catch {
    return null;
  }
  if (host === "reddit.com" || host === "redd.it" || host.endsWith(".reddit.com") || host.endsWith(".redd.it")) {
    return detectRedditBlock(html);
  }
  if (host.includes("amazon.") || host === "amzn.to" || host === "a.co" || host.endsWith(".amzn.to") || host.endsWith(".a.co")) {
    return detectAmazonBlock(html);
  }
  return null;
}
function cleanHtml(html, url) {
  try {
    const { document } = parseHTML(html);
    stripBoilerplateDom(document);
    return document.toString();
  } catch (err) {
    log.warn("boilerplate DOM pre-pass failed", { url, error: String(err) });
    return html;
  }
}
function trySiteExtractors(cleanedHtml, url, originalHtml) {
  const extractors = getSiteExtractors();
  const match = extractors.find((e) => e.canHandle(url, originalHtml));
  if (!match) return null;
  return match.extract(cleanedHtml, url);
}
async function fallbackChain(cleanedHtml, url, _type) {
  const fromDefuddle = await defuddleExtract(cleanedHtml, url);
  if (fromDefuddle) return fromDefuddle;
  const fromReadability = readabilityExtract(cleanedHtml, url);
  if (fromReadability) return fromReadability;
  return {
    title: "",
    markdown: htmlToMarkdown(cleanedHtml),
    metadata: {},
    links: [],
    images: [],
    extractor: "turndown"
  };
}
export {
  routedExtract
};
//# sourceMappingURL=routed.js.map