import { XMLParser } from 'fast-xml-parser';
import OpenAI from 'openai';
import * as cheerio from 'cheerio';
import { downloadAndStoreImage } from './images';
import { publishPost } from './publisher';
import { readCms, slugify, writeCms } from './cms';
import { scrapeArticle, closeBrowser } from './puppeteerScraper';

const rssUrl = 'https://tass.ru/rss/v2.xml';

type RssItem = {
  title?: string;
  link?: string;
  description?: string;
  pubDate?: string;
  enclosure?: {
    '@_url'?: string;
    '@_type'?: string;
  };
  'media:content'?: {
    '@_url'?: string;
    '@_type'?: string;
  };
  'media:thumbnail'?: {
    '@_url'?: string;
  };
};

type TranslatedPost = {
  title: string;
  excerpt: string;
  body: string[];
  category: string;
  readTime: string;
};

// DONT USE ENV FOR THIS
const getOpenAIClient = () => new OpenAI({
  apiKey:   'sk-C9kUNuxFPA6Jvpi2stzikxzZMJzPuYy5TIoJEJiVR89oeiD6',
  baseURL:  'https://api.gapgpt.app/v1',
});

const getModel = () => 'gpt-5-nano';

const fetchText = async (url: string) => {
  // Try plain fetch first
  try {
    const response = await fetch(url, {
      headers: {
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
        accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'accept-language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
        referer: 'https://tass.ru/',
      },
      signal: AbortSignal.timeout(8000),
    });

    if (response.ok) {
      return response.text();
    }
  } catch {}

  // Fallback: use Puppeteer
  const browser = await getBrowser();
  const page = await browser.newPage();
  try {
    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
    await new Promise((r) => setTimeout(r, 1000));
    const content = await page.evaluate(() => {
      const pre = document.querySelector('pre');
      if (pre) return pre.textContent || '';
      return document.body.innerText || document.body.textContent || '';
    });
    return content;
  } finally {
    await page.close();
  }
};

export const getTassFeedLinks = async (limit = 50) => {
  const xml = await fetchText(rssUrl);
  const parser = new XMLParser({ ignoreAttributes: false });
  const parsed = parser.parse(xml);
  const rawItems = parsed?.rss?.channel?.item ?? [];
  const items = Array.isArray(rawItems) ? rawItems : [rawItems];

  return (items.slice(0, limit) as RssItem[])
    .map((item) => item.link)
    .filter(Boolean) as string[];
};

const getItems = async (limit: number) => {
  const xml = await fetchText(rssUrl);
  const parser = new XMLParser({ ignoreAttributes: false });
  const parsed = parser.parse(xml);
  const rawItems = parsed?.rss?.channel?.item ?? [];
  const items = Array.isArray(rawItems) ? rawItems : [rawItems];

  return items.slice(0, Math.max(limit * 10, 30)) as RssItem[];
};

const stripHtml = (value = '') => {
  if (!value) return '';
  const $ = cheerio.load(value);
  return $.text().replace(/\s+/g, ' ').trim();
};

const getRssImage = (item: RssItem) => {
  const candidates = [
    item.enclosure?.['@_type']?.startsWith('image/') ? item.enclosure?.['@_url'] : '',
    item['media:content']?.['@_type']?.startsWith('image/') ? item['media:content']?.['@_url'] : '',
    item['media:thumbnail']?.['@_url'],
  ].filter(Boolean) as string[];

  return candidates.find((candidate) => candidate.startsWith('http')) ?? '';
};

const sortImageItemsFirst = (items: RssItem[]) => [...items].sort((first, second) => {
  const firstHasImage = getRssImage(first) ? 1 : 0;
  const secondHasImage = getRssImage(second) ? 1 : 0;

  return secondHasImage - firstHasImage;
});

const getFallbackArticle = (item: RssItem) => {
  const description = stripHtml(item.description);

  return {
    title: item.title ?? '',
    description,
    imageUrl: getRssImage(item),
    text: description,
    usedFallback: true,
  };
};

const toAbsoluteUrl = (value: string, baseUrl: string) => {
  try {
    return new URL(value, baseUrl).toString();
  } catch {
    return '';
  }
};

const extractArticleCheerio = async (url: string) => {
  const html = await fetchText(url);
  const $ = cheerio.load(html);

  const title =
    $('meta[property="og:title"]').attr('content') ||
    $('h1').first().text().replace(/\s+/g, ' ').trim();

  const description = $('meta[property="og:description"]').attr('content') || '';

  const imageCandidates = [
    $('meta[property="og:image"]').attr('content'),
    $('article img').first().attr('src'),
    $('img').first().attr('src'),
  ].filter(Boolean) as string[];

  const imageUrl =
    imageCandidates
      .map((c) => toAbsoluteUrl(c, url))
      .find(Boolean) ?? '';

  const paragraphs: string[] = [];
  $('article p, [data-content] p, .text-content p, p').each((_, el) => {
    const pText = $(el).text().replace(/\s+/g, ' ').trim();
    if (pText.length > 80) {
      paragraphs.push(pText);
    }
  });

  return {
    title,
    description,
    imageUrl,
    text: paragraphs.slice(0, 14).join('\n\n'),
  };
};

const extractArticle = async (url: string) => {
  try {
    const scraped = await scrapeArticle(url);
    if (scraped.text || scraped.title) {
      return {
        title: scraped.title,
        description: scraped.description,
        imageUrl: scraped.imageUrl,
        text: scraped.text,
        usedFallback: false,
      };
    }
  } catch {}

  // Fallback to cheerio
  const fallback = await extractArticleCheerio(url);
  return {
    ...fallback,
    usedFallback: true,
  };
};

const translateArticle = async (article: { title: string; description: string; text: string }): Promise<TranslatedPost> => {
  const client = getOpenAIClient();

  if (!client.apiKey) {
    throw new Error('GAPGPT_API_KEY or OPENAI_API_KEY is not configured');
  }

  const sourceText = article.text || article.description || article.title;

  if (!sourceText) {
    throw new Error('RSS item has no usable text');
  }

  const completion = await client.chat.completions.create({
    model: getModel(),
    messages: [
      {
        role: 'system',
        content: 'تو سردبیر فارسی یک سایت خبری هستی. متن روسی/انگلیسی خبر را به فارسی روان و خبری تبدیل کن. خروجی فقط JSON معتبر باشد.',
      },
      {
        role: 'user',
        content: JSON.stringify({
          instruction: 'ترجمه و بازنویسی خبری فارسی بساز. دسته یکی از اقتصاد، سیاست، انرژی، فناوری، بین‌الملل باشد. body آرایه پاراگراف‌ها باشد.',
          source: { ...article, text: sourceText },
          schema: {
            title: 'string',
            excerpt: 'string',
            category: 'string',
            readTime: 'string',
            body: ['string'],
          },
        }),
      },
    ],
    response_format: { type: 'json_object' },
    temperature: 0.3,
  });

  const content = completion.choices[0]?.message?.content ?? '{}';
  const jsonText = content.match(/\{[\s\S]*\}/)?.[0] ?? content;
  const parsed = JSON.parse(jsonText) as Partial<TranslatedPost>;

  return {
    title: parsed.title?.trim() || article.title,
    excerpt: parsed.excerpt?.trim() || article.description,
    category: parsed.category?.trim() || 'بین‌الملل',
    readTime: parsed.readTime?.trim() || '۳ دقیقه',
    body: Array.isArray(parsed.body) ? parsed.body.map(String).filter(Boolean) : [article.text],
  };
};

export const runTassAgent = async (limit = 3) => {
  const cms = await readCms();
  const processedLinks = new Set(cms.settings.agents?.tass?.processedLinks ?? []);
  const items = sortImageItemsFirst(await getItems(limit));
  const created = [];
  const failed = [];
  const skipped = [];

  for (const item of items) {
    if (created.length >= limit) {
      break;
    }

    const link = item.link;

    if (!link) {
      continue;
    }

    if (processedLinks.has(link)) {
      skipped.push(link);
      continue;
    }

    try {
      let article = getFallbackArticle(item);
      let extractionWarning = '';

      try {
        const extractedArticle = await extractArticle(link);
        article = {
          ...article,
          ...extractedArticle,
          title: extractedArticle.title || article.title,
          description: extractedArticle.description || article.description,
          imageUrl: extractedArticle.imageUrl || article.imageUrl,
          text: extractedArticle.text || article.text,
        };
      } catch (error) {
        extractionWarning = error instanceof Error ? error.message : 'Article extraction failed';
      }

      const translated = await translateArticle({
        title: article.title || item.title || '',
        description: article.description || item.description || '',
        text: article.text || item.description || '',
      });
      
      const storedImage = article.imageUrl ? await downloadAndStoreImage(article.imageUrl) : null;
      const body = [...translated.body];

      if (storedImage?.image) {
        body.splice(1, 0, `[image:${storedImage.image}|${translated.title}]`);
      }

      const post = await publishPost({
        title: translated.title,
        slug: slugify(`${translated.title}-${Date.now()}`),
        category: translated.category,
        readTime: translated.readTime,
        excerpt: translated.excerpt,
        body,
        status: 'pending',
        image: storedImage?.image,
        thumbnail: storedImage?.thumbnail,
        sourceUrl: link,
      });
      processedLinks.add(link);

      created.push({
        slug: post.slug,
        title: post.title,
        source: link,
        sourceImage: article.imageUrl || undefined,
        image: storedImage?.image,
        thumbnail: storedImage?.thumbnail,
        warning: extractionWarning || undefined,
      });
    } catch (error) {
      failed.push({ source: link, error: error instanceof Error ? error.message : 'Unknown error' });
    }
  }

  const latestCms = await readCms();
  latestCms.settings.agents = {
    ...latestCms.settings.agents,
    tass: {
      processedLinks: Array.from(processedLinks),
    },
  };
  await writeCms(latestCms);

  await closeBrowser();

  return { created, failed, skipped };
};
