import puppeteer, { type Browser } from 'puppeteer-core';
import { existsSync } from 'node:fs';

let browserInstance: Browser | null = null;

const getChromePath = (): string => {
  const platform = process.platform;

  if (platform === 'darwin') {
    const paths = [
      '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
      '/Applications/Chromium.app/Contents/MacOS/Chromium',
      '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser',
    ];
    for (const p of paths) {
      if (existsSync(p)) return p;
    }
  }

  if (platform === 'linux') {
    const paths = [
      '/usr/bin/google-chrome',
      '/usr/bin/google-chrome-stable',
      '/usr/bin/chromium',
      '/usr/bin/chromium-browser',
      '/snap/bin/chromium',
    ];
    for (const p of paths) {
      if (existsSync(p)) return p;
    }
  }

  if (platform === 'win32') {
    const paths = [
      'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
      'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
    ];
    for (const p of paths) {
      if (existsSync(p)) return p;
    }
  }

  return '';
};

export const getBrowser = async (): Promise<Browser> => {
  if (browserInstance && browserInstance.connected) {
    return browserInstance;
  }

  const chromePath = process.env.PUPPETEER_EXECUTABLE_PATH || getChromePath();
  if (!chromePath) {
    throw new Error('Chrome/Chromium not found. Install Chrome or set PUPPETEER_EXECUTABLE_PATH.');
  }

  browserInstance = await puppeteer.launch({
    executablePath: chromePath,
    headless: true,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage',
      '--disable-gpu',
      '--window-size=1920,1080',
    ],
  });

  return browserInstance;
};

export const closeBrowser = async () => {
  if (browserInstance) {
    await browserInstance.close();
    browserInstance = null;
  }
};

export type ScrapedArticle = {
  title: string;
  description: string;
  imageUrl: string;
  text: string;
  allImages: string[];
};

export const scrapeArticle = async (url: string): Promise<ScrapedArticle> => {
  const browser = await getBrowser();
  const page = await browser.newPage();

  try {
    await page.setViewport({ width: 1920, height: 1080 });
    await page.setUserAgent(
      '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'
    );

    // Block fonts, media, stylesheets to speed up page load
    await page.setRequestInterception(true);
    page.on('request', (req) => {
      const type = req.resourceType();
      if (['font', 'media'].includes(type)) {
        req.abort();
      } else {
        req.continue();
      }
    });

    await page.goto(url, {
      waitUntil: 'domcontentloaded',
      timeout: 60000,
    });

    // Wait for content to settle
    await new Promise((r) => setTimeout(r, 2000));

    const data = await page.evaluate(() => {
      const title =
        document.querySelector('meta[property="og:title"]')?.getAttribute('content') ||
        document.querySelector('h1')?.textContent?.trim() ||
        document.title;

      const description =
        document.querySelector('meta[property="og:description"]')?.getAttribute('content') ||
        document.querySelector('meta[name="description"]')?.getAttribute('content') ||
        '';

      const ogImage = document.querySelector('meta[property="og:image"]')?.getAttribute('content') || '';

      // Collect article-specific images (avoid tracking pixels, logos, sidebar)
      const allImages: string[] = [];
      const imageBlacklist = ['logo', 'icon', 'avatar', 'counter', 'yadro', 'pixel', 'track', '1x1', 'badge'];
      document.querySelectorAll('img').forEach((img) => {
        const src = img.getAttribute('src') || img.getAttribute('data-src') || '';
        if (!src) return;
        const lowerSrc = src.toLowerCase();
        if (imageBlacklist.some(b => lowerSrc.includes(b))) return;
        // Skip tiny images (likely icons/pixels)
        const width = parseInt(img.getAttribute('width') || '0');
        const height = parseInt(img.getAttribute('height') || '0');
        if ((width > 0 && width < 50) || (height > 0 && height < 50)) return;
        try {
          allImages.push(new URL(src, window.location.origin).href);
        } catch {}
      });

      // Try to find the main article image from content area
      const contentContainer = document.querySelector('[class*="ContentPageContainer_content"]') ||
                                document.querySelector('article') ||
                                document.querySelector('[data-content]');
      const articleImage = contentContainer?.querySelector('img')?.getAttribute('src') || '';

      const imageUrl = ogImage || articleImage || '';

      // Extract paragraphs from article content
      const paragraphs: string[] = [];

      // Build a set of footer/legal text to exclude
      const footerTexts = new Set<string>();
      document.querySelectorAll('[class*="Legal"], [class*="legal"], [class*="footer"], [class*="Footer"], [class*="Copyright"], [class*="copyright"], [class*="sidebar"], [class*="Sidebar"]').forEach(el => {
        el.querySelectorAll('p, li').forEach(p => {
          const t = p.textContent?.trim().replace(/\s+/g, ' ') || '';
          if (t) footerTexts.add(t);
        });
      });

      const selectors = [
        '[class*="ContentPageContainer_content"] p',
        '[class*="article"] p',
        '[class*="Article"] p',
        '[class*="news-text"] p',
        '[class*="detail"] p',
        '[class*="topic"] p',
        'article p',
        '[data-content] p',
        '.text-content p',
        '.article-body p',
      ];

      for (const selector of selectors) {
        document.querySelectorAll(selector).forEach((el) => {
          const text = el.textContent?.trim().replace(/\s+/g, ' ') || '';
          if (text.length > 20 && !paragraphs.includes(text) && !footerTexts.has(text)) {
            paragraphs.push(text);
          }
        });
        if (paragraphs.length > 0) break;
      }

      // Fallback: grab all paragraphs from main
      if (paragraphs.length < 2) {
        document.querySelectorAll('main p, .content p, .post-content p').forEach((el) => {
          const text = el.textContent?.trim().replace(/\s+/g, ' ') || '';
          if (text.length > 30 && !paragraphs.includes(text) && !footerTexts.has(text)) {
            paragraphs.push(text);
          }
        });
      }

      // Last resort: any long paragraph
      if (paragraphs.length < 2) {
        document.querySelectorAll('p').forEach((el) => {
          const text = el.textContent?.trim().replace(/\s+/g, ' ') || '';
          if (text.length > 60 && !paragraphs.includes(text) && !footerTexts.has(text)) {
            paragraphs.push(text);
          }
        });
      }

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

    // Resolve relative URLs
    const resolvedImages = data.allImages.map((img) => {
      try {
        return new URL(img, url).href;
      } catch {
        return img;
      }
    });

    return {
      ...data,
      allImages: resolvedImages,
      imageUrl: data.imageUrl
        ? (() => {
            try {
              return new URL(data.imageUrl, url).href;
            } catch {
              return data.imageUrl;
            }
          })()
        : '',
    };
  } finally {
    await page.close();
  }
};
