#!/usr/bin/env node
/**
 * Screenshot capture script for PropertyWebBuilder
 * Takes screenshots of all pages across all themes
 * Automatically compresses images to stay under 2MB
 */

const { chromium } = require('playwright');
const path = require('path');
const fs = require('fs');

// Try to load sharp for compression, fall back gracefully if not available
let sharp;
try {
  sharp = require('sharp');
} catch (e) {
  console.log('Note: sharp not installed. Run "npm install" to enable auto-compression.');
}

const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';

// Generate date string in YYYY-MM-DD format
function getDateString() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

const DATE_STRING = getDateString();
const SCREENSHOT_DIR = path.join(__dirname, '..', 'docs', 'screenshots', 'dev', DATE_STRING);
const THEME = process.env.SCREENSHOT_THEME || 'default';
const MAX_SIZE_MB = parseFloat(process.env.MAX_SIZE_MB || '2');
const MAX_SIZE_BYTES = MAX_SIZE_MB * 1024 * 1024;

// Build URL with theme parameter (unless theme is 'default')
function buildUrl(basePath) {
  const url = `${BASE_URL}${basePath}`;
  if (THEME === 'default') return url;
  const separator = url.includes('?') ? '&' : '?';
  return `${url}${separator}theme=${THEME}`;
}

// Pages to capture for each theme
const PAGES = [
  { name: 'home', path: '/' },
  { name: 'home-en', path: '/en' },
  { name: 'buy', path: '/en/buy' },
  { name: 'rent', path: '/en/rent' },
  { name: 'sell', path: '/p/sell' },
  { name: 'contact', path: '/contact-us' },
  { name: 'about', path: '/about-us' },
];

// Dynamic pages that need to be discovered (e.g., property detail pages)
const DYNAMIC_PAGES = [
  {
    name: 'property-sale',
    discoverFrom: '/en/buy',
    linkSelector: 'a[href*="/properties/for-sale/"]',
    description: 'Property for sale detail page'
  },
  {
    name: 'property-rent',
    discoverFrom: '/en/rent',
    linkSelector: 'a[href*="/properties/for-rent/"]',
    description: 'Property for rent detail page'
  },
];

// Admin pages (require authentication bypass or logged in state)
const ADMIN_PAGES = [
  { name: 'dashboard', path: '/site_admin' },
  { name: 'properties', path: '/site_admin/props' },
  { name: 'settings', path: '/site_admin/website/settings' },
];

// Viewports for responsive screenshots
const VIEWPORTS = [
  { name: 'desktop', width: 1440, height: 900 },
  { name: 'tablet', width: 768, height: 1024 },
  { name: 'mobile', width: 375, height: 812 },
];

// Max dimensions for compression
const MAX_DESKTOP_WIDTH = 1440;
const MAX_MOBILE_WIDTH = 750;

async function ensureDir(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}

async function getFileSizeMB(filepath) {
  const stats = fs.statSync(filepath);
  return stats.size / (1024 * 1024);
}

async function compressImage(filepath, isMobile = false) {
  if (!sharp) return;
  
  const originalSize = await getFileSizeMB(filepath);
  if (originalSize <= MAX_SIZE_MB) {
    return; // Already under limit
  }
  
  console.log(`    Compressing ${path.basename(filepath)} (${originalSize.toFixed(2)}MB)...`);
  
  const maxWidth = isMobile ? MAX_MOBILE_WIDTH : MAX_DESKTOP_WIDTH;
  const tempPath = filepath.replace('.png', '.temp.png');
  
  try {
    let image = sharp(filepath);
    const metadata = await image.metadata();
    
    // Resize if needed
    if (metadata.width > maxWidth) {
      image = image.resize(maxWidth, null, { 
        withoutEnlargement: true,
        fit: 'inside'
      });
    }
    
    // Apply PNG compression with palette for smaller size
    await image
      .png({ 
        compressionLevel: 9,
        adaptiveFiltering: true,
        palette: true,
        quality: 80
      })
      .toFile(tempPath);
    
    let newSize = await getFileSizeMB(tempPath);
    
    // If still too large, be more aggressive
    if (newSize > MAX_SIZE_MB) {
      // Reduce colors and resize more
      await sharp(filepath)
        .resize(Math.floor(maxWidth * 0.8), null, { withoutEnlargement: true, fit: 'inside' })
        .png({ 
          compressionLevel: 9,
          palette: true,
          colors: 128
        })
        .toFile(tempPath);
      
      newSize = await getFileSizeMB(tempPath);
    }
    
    // Replace original
    fs.unlinkSync(filepath);
    fs.renameSync(tempPath, filepath);
    
    console.log(`    Compressed to ${newSize.toFixed(2)}MB`);
    
  } catch (error) {
    if (fs.existsSync(tempPath)) {
      fs.unlinkSync(tempPath);
    }
    console.error(`    Compression failed: ${error.message}`);
  }
}

async function takeScreenshot(page, theme, pageName, viewport) {
  const dir = path.join(SCREENSHOT_DIR, theme);
  await ensureDir(dir);

  const filename = `${pageName}-${viewport.name}.png`;
  const filepath = path.join(dir, filename);
  const isMobile = viewport.name === 'mobile';

  await page.setViewportSize({ width: viewport.width, height: viewport.height });
  await page.screenshot({ path: filepath, fullPage: true });

  const sizeMB = await getFileSizeMB(filepath);
  console.log(`  Captured: ${filename} (${sizeMB.toFixed(2)}MB)`);
  
  // Auto-compress if over limit
  if (sizeMB > MAX_SIZE_MB) {
    await compressImage(filepath, isMobile);
  }

  return filepath;
}

async function discoverAndCaptureDynamicPage(page, themeName, dynamicPage) {
  console.log(`  Discovering ${dynamicPage.description}...`);

  try {
    // Navigate to the discovery page (with theme parameter)
    const discoverUrl = buildUrl(dynamicPage.discoverFrom);
    await page.goto(discoverUrl, { waitUntil: 'networkidle', timeout: 30000 });
    await page.waitForTimeout(1000);

    // Find the first matching link
    const link = await page.$(dynamicPage.linkSelector);
    if (!link) {
      console.log(`    No ${dynamicPage.name} link found on ${dynamicPage.discoverFrom}`);
      return;
    }

    const href = await link.getAttribute('href');
    if (!href) {
      console.log(`    Link found but no href attribute`);
      return;
    }

    // Navigate to the property page (with theme parameter)
    let propertyUrl = href.startsWith('http') ? href : `${BASE_URL}${href}`;
    if (THEME !== 'default') {
      const separator = propertyUrl.includes('?') ? '&' : '?';
      propertyUrl = `${propertyUrl}${separator}theme=${THEME}`;
    }
    console.log(`  Loading: ${propertyUrl}`);
    await page.goto(propertyUrl, { waitUntil: 'networkidle', timeout: 30000 });
    await page.waitForTimeout(1000);

    // Take screenshots
    await takeScreenshot(page, themeName, dynamicPage.name, VIEWPORTS[0]);
    await takeScreenshot(page, themeName, dynamicPage.name, VIEWPORTS[2]);

  } catch (error) {
    console.error(`  Error capturing ${dynamicPage.name}: ${error.message}`);
  }
}

async function captureTheme(browser, themeName) {
  console.log(`\nCapturing theme: ${themeName}`);

  const context = await browser.newContext();
  const page = await context.newPage();

  // Capture static pages
  for (const pageInfo of PAGES) {
    const url = buildUrl(pageInfo.path);
    console.log(`  Loading: ${url}`);

    try {
      await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 });
      await page.waitForTimeout(1000); // Wait for any animations

      // Take desktop screenshot (primary)
      await takeScreenshot(page, themeName, pageInfo.name, VIEWPORTS[0]);

      // Take mobile screenshot
      await takeScreenshot(page, themeName, pageInfo.name, VIEWPORTS[2]);

    } catch (error) {
      console.error(`  Error capturing ${pageInfo.name}: ${error.message}`);
    }
  }

  // Capture dynamic pages (property details, etc.)
  for (const dynamicPage of DYNAMIC_PAGES) {
    await discoverAndCaptureDynamicPage(page, themeName, dynamicPage);
  }

  await context.close();
}

async function main() {
  console.log('Starting screenshot capture...');
  console.log(`Base URL: ${BASE_URL}`);
  console.log(`Output directory: ${SCREENSHOT_DIR}`);
  console.log(`Max file size: ${MAX_SIZE_MB}MB`);
  if (!sharp) {
    console.log('Warning: sharp not available, compression disabled');
  }

  const browser = await chromium.launch({ headless: true });

  try {
    // Capture screenshots for the specified theme
    console.log(`Theme: ${THEME}`);
    await captureTheme(browser, THEME);

    console.log('\nScreenshot capture complete!');
    console.log(`Screenshots saved to: ${SCREENSHOT_DIR}/${THEME}`);

  } finally {
    await browser.close();
  }
}

main().catch(console.error);
