import puppeteer from 'puppeteer';
import fs from 'fs';
import path from 'path';
import { logger } from './logger';

const downloadPath = path.resolve(__dirname, '../../download');

if (!fs.existsSync(downloadPath)) {
    fs.mkdirSync(downloadPath, { recursive: true });
}

async function downloadImage(url: string, filepath: string) {
    const response = await fetch(url);
    const buffer = await response.arrayBuffer();
    fs.writeFileSync(filepath, Buffer.from(buffer));
}

export async function downloadPinterestImages(keyword: string, numberOfPages: number): Promise<string[]> {
    const browser = await puppeteer.launch({ headless: true });
    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 });

    const encodedKeyword = encodeURIComponent(keyword);
    await page.goto(`https://www.pinterest.com/search/pins/?q=${encodedKeyword}`, { waitUntil: 'networkidle2' });

    logger.debug('Searching for:', keyword);

    try {
        await page.waitForSelector('img[src*="i.pinimg.com"]', { timeout: 10000 });
    } catch (error) {
        logger.error('Could not find images on the page. Pinterest might have changed its layout or is blocking the scraper.');
        await browser.close();
        return [];
    }

    let imageCount = 0;
    const downloadedUrls = new Set<string>();
    const downloadedImagePaths: string[] = [];

    for (let i = 0; i < numberOfPages; i++) {
        logger.debug(`Scraping page ${i + 1}...`);
        try {
            const imageUrls = await page.evaluate(() => {
                const images = Array.from(document.querySelectorAll('img[src*="i.pinimg.com"]'));
                return images.map(img => {
                    const image = img as HTMLImageElement;
                    const srcset = image.srcset;
                    if (srcset) {
                        const sources = srcset.split(',').map(s => s.trim().split(' ')[0]);
                        return sources[sources.length - 1];
                    }
                    return image.src;
                }).filter(Boolean);
            });

            for (const url of imageUrls) {
                if (!downloadedUrls.has(url)) {
                    downloadedUrls.add(url);
                    const extension = path.extname(new URL(url).pathname) || '.jpg';
                    const filename = `${keyword.replace(/ /g, '_')}_${imageCount++}${extension}`;
                    const filepath = path.join(downloadPath, filename);
                    logger.debug(`Downloading ${url} to ${filepath}`);
                    await downloadImage(url, filepath);
                    downloadedImagePaths.push(filepath);
                }
            }

            const previousHeight = await page.evaluate('document.body.scrollHeight');
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');

            try {
                await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`, { timeout: 10000 });
            } catch (e) {
                logger.debug('No more content to load.');
                break;
            }

            await new Promise(resolve => setTimeout(resolve, 1000)); // Small delay for images to render
        } catch (error) {
            logger.error(`An error occurred while scraping page ${i + 1}:`, error);
            logger.debug('Stopping the scraping process due to an error.');
            break;
        }
    }

    await browser.close();
    logger.debug('Done.');
    return downloadedImagePaths;
}
