import * as cheerio from 'cheerio';
import fs from 'fs';
import path from 'path';
import { pingDailyPuzzleUpdated } from '../services/indexingService';
import { launchBrowser } from './puppeteer-launcher';

export async function generateQuordleHints() {
  try {
    // 1️⃣ Figure out today's date & matching Quordle ID
    const today = new Date();
    const baseDate = new Date('2025-06-28');
    const baseId = 1251;
    const offset = Math.floor(
      (today.getTime() - baseDate.getTime()) / (1000 * 60 * 60 * 24)
    );
    const calculatedQuordleId = baseId + offset;

    const monthSlug = today
      .toLocaleString('en-US', { month: 'long' })
      .toLowerCase();
    const dayNum = today.getDate();

    const ordinal = (n: number): string => {
      if ([11, 12, 13].includes(n % 100)) return `${n}th`;
      const suffixes = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th'];
      return `${n}${suffixes[n % 10]}`;
    };

    const daySlug = ordinal(dayNum);
    const year = today.getFullYear();

    const dateStr = today.toISOString().split('T')[0];

    const out = {
      date: dateStr,
      id: calculatedQuordleId,
      answers: [] as string[],
      source: '',
    };

    // Primary source: Beebom (static URL updated daily, fast and reliable)
    const beebomUrl = 'https://beebom.com/puzzle/quordle-hints-answers-today/';
    try {
      console.log(`[Quordle] Fetching primary source: ${beebomUrl}`);
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 12000);
      const res = await fetch(beebomUrl, {
        headers: {
          'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
          Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        },
        signal: controller.signal,
      });
      clearTimeout(timeoutId);

      if (res.ok) {
        const html = await res.text();

        // Strategy A: JSON-LD / FAQ answer pattern
        const schemaMatch = html.match(
          /puzzle\s*#?(\d+)[^]+?is\s*<strong[^>]*>([A-Za-z]{5})<\\?\/strong>[^<]+<strong[^>]*>([A-Za-z]{5})<\\?\/strong>[^<]+<strong[^>]*>([A-Za-z]{5})<\\?\/strong>[^<]+<strong[^>]*>([A-Za-z]{5})<\\?\/strong>/i
        );

        if (schemaMatch) {
          const parsedId = parseInt(schemaMatch[1], 10);
          if (!isNaN(parsedId)) out.id = parsedId;
          out.answers = [
            schemaMatch[2].toUpperCase(),
            schemaMatch[3].toUpperCase(),
            schemaMatch[4].toUpperCase(),
            schemaMatch[5].toUpperCase(),
          ];
          out.source = beebomUrl;
          console.log(`[Quordle] Successfully extracted answers from Beebom schema: ${out.answers.join(', ')} (ID: ${out.id})`);
        } else {
          // Strategy B: Cheerio parse HTML headings
          const $ = cheerio.load(html);
          const headings = $('h2, h3, h4').filter((_, el) => {
            const txt = $(el).text().toLowerCase();
            return (
              txt.includes('answer') ||
              txt.includes('solution') ||
              txt.includes('classic') ||
              txt.includes('quordle')
            );
          });

          const foundAnswers: string[] = [];
          headings.each((_, h) => {
            if (foundAnswers.length === 4) return false;
            let next = $(h).next();
            let depth = 0;
            while (next.length && depth < 6 && foundAnswers.length < 4) {
              next.find('strong, b, li').each((_, el) => {
                const word = $(el).text().trim().toUpperCase();
                if (/^[A-Z]{5}$/.test(word) && !foundAnswers.includes(word)) {
                  foundAnswers.push(word);
                }
                if (foundAnswers.length === 4) return false;
              });
              next = next.next();
              depth++;
            }
          });

          if (foundAnswers.length === 4) {
            out.answers = foundAnswers;
            out.source = beebomUrl;
            console.log(`[Quordle] Successfully extracted answers from Beebom headings: ${out.answers.join(', ')}`);
          }
        }
      } else {
        console.warn(`[Quordle] Beebom returned HTTP ${res.status}`);
      }
    } catch (e: any) {
      console.warn(`[Quordle] Beebom fetch error: ${e.message}`);
    }

    // Fallback source: Candidate URLs with Puppeteer if primary source failed
    if (out.answers.length !== 4) {
      console.log('[Quordle] Primary source incomplete, attempting Puppeteer fallback...');
      const candidateUrls = [
        `https://fortniteinsider.com/quordle-answers-today-${monthSlug}-${daySlug}-${year}-${calculatedQuordleId}-hints/`,
        `https://fortniteinsider.com/quordle-today-answers-hints-${monthSlug}-${dayNum}-${year}/`,
        `https://fortniteinsider.com/quordle-answers-today/`,
      ];

      let html = '';
      let browser;
      try {
        browser = await launchBrowser();
        const page = await browser.newPage();
        page.setDefaultNavigationTimeout(60000);
        await page.setExtraHTTPHeaders({
          'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        });

        for (const targetUrl of candidateUrls) {
          try {
            await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
            html = await page.content();
            if (html && (html.toLowerCase().includes('daily quordle') || html.toLowerCase().includes('quordle answer'))) {
              out.source = targetUrl;
              break;
            }
          } catch (err: any) {
            console.warn(`[Quordle] Failed navigation to ${targetUrl}: ${err.message}`);
          }
        }
      } catch (e: any) {
        console.warn(`[Quordle] Browser launch warning: ${e.message}`);
      } finally {
        if (browser) {
          try {
            await browser.close();
          } catch (_) {}
        }
      }

      if (html) {
        const $ = cheerio.load(html);
        const headings = $('h1, h2, h3, h4').filter((_, el) => {
          const txt = $(el).text().toLowerCase();
          return (
            txt.includes('daily quordle classic') ||
            (txt.includes('quordle') && (txt.includes('classic') || txt.includes('answer') || txt.includes('solution')))
          );
        });

        const answers: string[] = [];
        headings.each((_, h) => {
          if (answers.length === 4) return false;
          let next = $(h).next();
          let depth = 0;
          while (next.length && depth < 5) {
            const tag = next.get(0)?.tagName?.toLowerCase() || '';
            if (['ul', 'ol'].includes(tag)) {
              next.find('li').each((_, li) => {
                const word = $(li).text().trim().toUpperCase();
                if (/^[A-Z]{5}$/.test(word) && !answers.includes(word)) {
                  answers.push(word);
                }
                if (answers.length === 4) return false;
              });
            } else if (tag === 'p') {
              const pText = next.text();
              const words = pText.match(/\b[A-Za-z]{5}\b/g) || [];
              for (const w of words) {
                const upper = w.toUpperCase();
                if (!answers.includes(upper)) {
                  answers.push(upper);
                }
                if (answers.length === 4) break;
              }
            }
            if (answers.length === 4) return false;
            next = next.next();
            depth++;
          }
        });

        out.answers = answers;
      }
    }

    if (out.answers.length === 4) {
      const fileName = `${out.date}.json`;
      const baseDir = path.join(__dirname, '..', '..', '..');
      const targetDirs = [
        path.join(baseDir, 'project', 'public', 'hints', 'qourdle'),
        path.join(baseDir, 'project', 'dist', 'client', 'hints', 'qourdle'),
        path.join(baseDir, 'nytsolvers', 'dist', 'client', 'hints', 'qourdle'),
        path.join(baseDir, 'project', 'public', 'hints', 'quordle'),
        path.join(baseDir, 'project', 'dist', 'client', 'hints', 'quordle'),
        path.join(baseDir, 'nytsolvers', 'dist', 'client', 'hints', 'quordle'),
        // Linux production paths
        '/var/www/nytsolvers/dist/client/hints/qourdle',
        '/var/www/nytsolvers/public/hints/qourdle',
        '/var/www/nytsolvers/dist/client/hints/quordle',
        '/var/www/nytsolvers/public/hints/quordle',
        '/var/www/project/dist/client/hints/qourdle',
        '/var/www/project/public/hints/qourdle',
        '/var/www/project/dist/client/hints/quordle',
        '/var/www/project/public/hints/quordle',
      ];

      for (const dir of targetDirs) {
        try {
          if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
          fs.writeFileSync(path.join(dir, fileName), JSON.stringify(out, null, 2));
          console.log(`[Quordle] Successfully written to: ${path.join(dir, fileName)}`);
        } catch (e) {}
      }

      // Trigger search engine indexing (Google Indexing API & Bing IndexNow)
      await pingDailyPuzzleUpdated('quordle-hints', out.date).catch((err: any) =>
        console.error('[Quordle] Error pinging search indexing:', err.message)
      );
    } else {
      console.warn(`[Quordle] Could not extract 4 answers for ${out.date}`);
    }
  } catch (error: any) {
    console.error('Error generating Quordle hints:', error.message);
  }
}

if (require.main === module) {
  generateQuordleHints();
}
