import { fetchFeed } from './fetcher.ts';
import type { FetchResult, UrlGuard } from './fetcher.ts';
import { parseFeed } from './parser.ts';

const COMMON_PATHS = [
  '/feed',
  '/rss',
  '/atom.xml',
  '/feed.xml',
  '/rss.xml',
  '/index.xml',
  '/feed/',
];

export async function discoverFeedUrl(inputUrl: string, guard?: UrlGuard): Promise<string> {
  // Try the URL itself first.
  try {
    const res = await fetchFeed(inputUrl, {}, guard);
    if (res.status === 200) {
      parseFeed(res.body, res.contentType); // throws if not a feed
      return res.url;
    }
  } catch {
    // not a direct feed; continue
  }

  // Fetch as HTML and look for <link rel="alternate"> feed links.
  let res: FetchResult | null;
  try {
    res = await fetchFeed(inputUrl, {}, guard);
  } catch {
    res = null;
  }
  if (res && res.status === 200) {
    const match = res.body.match(/<link[^>]+rel=["']alternate["'][^>]*>/gi) || [];
    for (const tag of match) {
      const typeMatch = tag.match(/type=["']([^"']+)["']/i);
      const hrefMatch = tag.match(/href=["']([^"']+)["']/i);
      const type = typeMatch ? typeMatch[1] : '';
      if (/rss|atom|json|xml/i.test(type) && hrefMatch) {
        try {
          return new URL(hrefMatch[1], res.url).toString();
        } catch {
          // ignore
        }
      }
    }
  }

  // Fallback common paths.
  const base = new URL(inputUrl);
  const origin = base.origin;
  for (const p of COMMON_PATHS) {
    const candidate = origin + p;
    try {
      const r = await fetchFeed(candidate, {}, guard);
      if (r.status === 200) {
        parseFeed(r.body, r.contentType);
        return r.url;
      }
    } catch {
      // try next
    }
  }

  throw new Error('could not discover feed');
}
