import { logger } from './logger';
import * as fs from 'fs/promises';
import dotenv from 'dotenv';
import path from 'path';
import puppeteer from 'puppeteer';

export async function getPinUrlFromPinterest(keyword: string): Promise<string | null> {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36');
    await page.setViewport({ width: 1920, height: 1080 });
    try {
        const searchUrl = `https://www.pinterest.com/search/pins/?q=${encodeURIComponent(keyword)}`;
        await page.goto(searchUrl, { waitUntil: 'networkidle2' });

        const scrollCount = Math.floor(Math.random() * 5) + 1;
        logger.info(`Scrolling ${scrollCount} times...`);
        for (let i = 0; i < scrollCount; i++) {
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
            await new Promise(resolve => setTimeout(resolve, Math.random() * 1000 + 1000));
        }

        const pinLinks = await page.$$eval('a', (anchors) =>
            anchors.map((a) => a.href).filter((href) => href.includes('/pin/'))
        );

        if (pinLinks.length > 0) {
            return pinLinks[Math.floor(Math.random() * pinLinks.length)];
        }
        return null;
    } catch (error) {
        logger.error('Error while getting pin URL from Pinterest:', error);
        return null;
    } finally {
        await browser.close();
    }
}

export async function downloadImagesFromPinterestSearch(keyword: string, count: number): Promise<string[]> {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36');
    await page.setViewport({ width: 1920, height: 1080 });
    try {
        const searchUrl = `https://www.pinterest.com/search/pins/?q=${encodeURIComponent(keyword)}`;
        await page.goto(searchUrl, { waitUntil: 'networkidle2' });

        logger.info(`Scrolling 3 times...`);
        for (let i = 0; i < 3; i++) {
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
            await new Promise(resolve => setTimeout(resolve, Math.random() * 1000 + 1000));
        }

        const imageUrls = await page.$$eval('img', (imgs) => {
            const urls: string[] = imgs.map(img => {
                const srcset = img.getAttribute('srcset') || '';
                if (!srcset) return '';
                const parts = srcset.split(',').map(p => p.trim());
                for (const part of parts) {
                    const m = part.match(/^(\S+)\s+4x$/);
                    if (m && m[1]) return m[1];
                }
                const src = img.src || '';
                if (src.includes('/originals/')) return src;
                return '';
            }).filter(s => !!s && s.includes('pinimg'));
            // Remove duplicates
            return [...new Set(urls)];
        });

        if (imageUrls.length === 0) {
            logger.warn(`No 4x image URLs found for keyword "${keyword}"`);
            return [];
        }

        // shuffle and pick up to `count` unique images
        const shuffled = imageUrls.slice().sort(() => 0.5 - Math.random());
        const chosen = shuffled.slice(0, Math.min(count, shuffled.length));

        const outDir = path.join(process.cwd(), 'download');
        await fs.mkdir(outDir, { recursive: true });

        const results: string[] = [];
        for (let i = 0; i < chosen.length; i++) {
            const src = chosen[i];
            try {
                const imgPage = await browser.newPage();
                const resp = await imgPage.goto(src, { timeout: 30000, waitUntil: 'networkidle2' });
                if (!resp) {
                    logger.warn(`Failed to fetch image ${src}`);
                    await imgPage.close();
                    continue;
                }
                const buffer = await resp.buffer();
                const timestamp = Date.now();
                const outPath = path.join(outDir, `${keyword.replace(/\s+/g, '_')}_${timestamp}_${i}.png`);
                await fs.writeFile(outPath, buffer);
                results.push(outPath);
                await imgPage.close();
            } catch (err) {
                logger.error(`Failed to download image ${src}:`, err);
            }
        }
        return results;

    } catch (error) {
        logger.error(`Error while downloading images for keyword "${keyword}":`, error);
        return [];
    } finally {
        await browser.close();
    }
}


// Download up to `count` images from a pin URL by opening the pin page and scro lling up to 5 times to trigger lazy loading
// Returns an array of saved image paths (may be empty)
export async function downloadImageFromPin(pinUrl: string, count: number = 1): Promise<string[]> {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36');
    await page.setViewport({ width: 1920, height: 1080 });
    try {
        await page.goto(pinUrl, { waitUntil: 'networkidle2', timeout: 30000 });
        for (let i = 0; i < 3; i++) {
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
            await new Promise((r) => setTimeout(r, 700 + Math.random() * 800));
        }

        const imgs: string[] = await page.$$eval('img', imgs => {
            // For each <img> try to extract the 4x (original) URL from srcset.
            // srcset example:
            // "https://i.pinimg.com/236x/...jpg 1x, https://i.pinimg.com/474x/...jpg 2x, https://i.pinimg.com/736x/...jpg 3x, https://i.pinimg.com/originals/...jpg 4x"
            const urls: string[] = imgs.map(img => {
                const srcset = (img as HTMLImageElement).getAttribute('srcset') || '';
                if (!srcset) return '';
                const parts = srcset.split(',').map(p => p.trim());
                for (const part of parts) {
                    const m = part.match(/^(\S+)\s+4x$/);
                    if (m && m[1]) return m[1];
                }
                // fallback: if src contains "originals" return src
                const src = (img as HTMLImageElement).src || '';
                if (src.includes('/originals/')) return src;
                return '';
            }).filter(s => !!s && s.includes('pinimg'));
            return urls;
        });

        if (!imgs || imgs.length === 0) {
            logger.warn(`No image src (4x) found on pin page ${pinUrl}`);
            return [];
        }

        // shuffle and pick up to `count` unique images
        const shuffled = imgs.slice().sort(() => 0.5 - Math.random());
        const chosen = shuffled.slice(0, Math.min(count, shuffled.length));

        const outDir = path.join(process.cwd(), 'download');
        await fs.mkdir(outDir, { recursive: true });

        const results: string[] = [];
        for (let i = 0; i < chosen.length; i++) {
            const src = chosen[i];
            try {
                const imgPage = await browser.newPage();
                const resp = await imgPage.goto(src, { timeout: 30000, waitUntil: 'networkidle2' });
                if (!resp) {
                    logger.warn(`Failed to fetch image ${src} from ${pinUrl}`);
                    await imgPage.close();
                    continue;
                }
                const buffer = await resp.buffer();
                const pinId = pinUrl.split('/').filter(Boolean).pop() || `pin_${Date.now()}`;
                const timestamp = Date.now();
                const outPath = path.join(outDir, `${pinId}_${timestamp}_${i}.png`);
                await fs.writeFile(outPath, buffer);
                results.push(outPath);
                await imgPage.close();
            } catch (err) {
                logger.error(`Failed to download image ${src} from ${pinUrl}:`, err);
            }
        }

        return results;
    } catch (err) {
        logger.error(`Failed to download images from ${pinUrl}:`, err);
        return [];
    } finally {
        await browser.close();
    }
}
