import { XMLParser } from "fast-xml-parser";

type NewsItem = {
  title: string;
  link: string;
  pubDate?: string;
};

const parser = new XMLParser({
  ignoreAttributes: false,
  attributeNamePrefix: "",
  trimValues: true,
});

function toArray<T>(value: T | T[] | undefined): T[] {
  if (!value) return [];
  return Array.isArray(value) ? value : [value];
}

function decodeGoogleNewsLink(link: string): string {
  return String(link || "").trim();
}

function escapeTitleForMarkdown(text: string): string {
  return String(text || "")
    .replace(/\\/g, "\\\\")
    .replace(/\[/g, "\\[")
    .replace(/\]/g, "\\]")
    .replace(/\(/g, "\\(")
    .replace(/\)/g, "\\)")
    .trim();
}

export const newsService = {
  async fetchGoogleNews(keyword?: string, limit = 10): Promise<NewsItem[]> {
    const q = String(keyword || "").trim();
    const endpoint = q
      ? `https://news.google.com/rss/search?q=${encodeURIComponent(q)}&hl=ko&gl=KR&ceid=KR:ko`
      : "https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko";

    const response = await fetch(endpoint, {
      headers: {
        "User-Agent": "discord-multibot-news/0.1",
        Accept: "application/rss+xml, application/xml, text/xml;q=0.9, */*;q=0.8",
      },
    });

    if (!response.ok) {
      throw new Error(`뉴스 요청 실패: HTTP ${response.status}`);
    }

    const xml = await response.text();
    const parsed = parser.parse(xml);
    const channel = parsed?.rss?.channel;
    const items = toArray(channel?.item);

    return items
      .map((item: any) => ({
        title: String(item?.title || "").trim(),
        link: decodeGoogleNewsLink(String(item?.link || "").trim()),
        pubDate: String(item?.pubDate || "").trim(),
      }))
      .filter((n) => n.title && n.link)
      .slice(0, Math.max(1, Math.min(limit, 10)));
  },

  toDiscordMessageChunks(title: string, items: NewsItem[], maxLen = 1900): string[] {
    const safeMax = Math.max(800, Math.min(maxLen, 1990));
    if (!items.length) return [`**${title}**\n표시할 뉴스가 없습니다.`];

    const lines = items.map((n, i) => {
      const compactTitle =
        n.title.length > 120 ? `${n.title.slice(0, 117).trim()}...` : n.title;
      // Wrap URL with <> to keep clickable link while preventing auto-embed cards.
      return `${i + 1}. [${escapeTitleForMarkdown(compactTitle)}](<${n.link}>)`;
    });

    const chunks: string[] = [];
    let current = `**${title}**\n`;

    for (const line of lines) {
      const next = `${current}${line}\n`;
      if (next.length > safeMax) {
        chunks.push(current.trimEnd());
        current = `${line}\n`;
      } else {
        current = next;
      }
    }
    if (current.trim()) chunks.push(current.trimEnd());
    return chunks;
  },
};
