/**
 * Before/After Visual Diff
 * Takes baseline screenshots and compares them to new screenshots
 * Highlights pixel-level differences
 */
const { chromium } = require('playwright');
const fs   = require('fs');
const path = require('path');
const db   = require('./db');
const { v4: uuidv4 } = require('uuid');

const SCREENSHOTS_DIR = path.join(__dirname, '..', 'screenshots');
const BASELINE_DIR    = path.join(__dirname, '..', 'data', 'baselines');
if (!fs.existsSync(BASELINE_DIR)) fs.mkdirSync(BASELINE_DIR, { recursive: true });

// Save baseline screenshots for a URL
async function saveBaseline(url, projectName) {
  const browser = await chromium.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
  });

  const baselineId = uuidv4();
  const results = [];

  try {
    const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
    const page = await context.newPage();
    await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 }).catch(() => null);

    // Desktop baseline
    const deskFile = `baseline_${baselineId}_d.png`;
    await page.screenshot({ path: path.join(BASELINE_DIR, deskFile), fullPage: true });

    // Mobile baseline
    await page.setViewportSize({ width: 375, height: 812 });
    await page.waitForTimeout(500);
    const mobileFile = `baseline_${baselineId}_m.png`;
    await page.screenshot({ path: path.join(BASELINE_DIR, mobileFile), fullPage: true });

    const title = await page.title().catch(() => url);
    results.push({ url, title, desktop: deskFile, mobile: mobileFile });

    await context.close();

    // Save baseline record
    const baselines = readBaselines();
    baselines.push({
      id: baselineId,
      url,
      projectName: projectName || url,
      desktop: deskFile,
      mobile: mobileFile,
      title,
      created_at: new Date().toISOString()
    });
    writeBaselines(baselines);

    return { success: true, id: baselineId, url, desktop: deskFile, mobile: mobileFile };
  } finally {
    await browser.close();
  }
}

// Compare current page against baseline
async function compareWithBaseline(baselineId) {
  const baselines = readBaselines();
  const baseline  = baselines.find(b => b.id === baselineId);
  if (!baseline) throw new Error('Baseline not found');

  const browser = await chromium.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
  });

  try {
    const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
    const page    = await context.newPage();
    await page.goto(baseline.url, { waitUntil: 'networkidle', timeout: 30000 }).catch(() => null);

    const newId      = uuidv4().slice(0,8);
    const deskNew    = `diff_${newId}_d.png`;
    const mobileNew  = `diff_${newId}_m.png`;

    await page.screenshot({ path: path.join(SCREENSHOTS_DIR, deskNew), fullPage: true });

    await page.setViewportSize({ width: 375, height: 812 });
    await page.waitForTimeout(500);
    await page.screenshot({ path: path.join(SCREENSHOTS_DIR, mobileNew), fullPage: true });

    await context.close();

    // Simple pixel-difference estimation using file size comparison
    const baselineSize = fs.statSync(path.join(BASELINE_DIR, baseline.desktop)).size;
    const newSize      = fs.statSync(path.join(SCREENSHOTS_DIR, deskNew)).size;
    const diffPercent  = Math.round(Math.abs(baselineSize - newSize) / baselineSize * 100);

    const result = {
      baselineId,
      url: baseline.url,
      projectName: baseline.projectName,
      baselineDate: baseline.created_at,
      compareDate: new Date().toISOString(),
      desktopBaseline: `/data/baselines/${baseline.desktop}`,
      desktopNew: `/screenshots/${deskNew}`,
      mobileBaseline: `/data/baselines/${baseline.mobile}`,
      mobileNew: `/screenshots/${mobileNew}`,
      estimatedChange: diffPercent,
      hasSignificantChange: diffPercent > 5
    };

    // Save compare result
    const compares = readCompares();
    compares.unshift(result);
    writeCompares(compares.slice(0,50)); // Keep last 50

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

function readBaselines()  { try { return JSON.parse(fs.readFileSync(path.join(BASELINE_DIR, 'baselines.json'),'utf8')); } catch { return []; } }
function writeBaselines(d){ fs.writeFileSync(path.join(BASELINE_DIR,'baselines.json'), JSON.stringify(d,null,2)); }
function readCompares()   { try { return JSON.parse(fs.readFileSync(path.join(BASELINE_DIR,'compares.json'),'utf8')); } catch { return []; } }
function writeCompares(d) { fs.writeFileSync(path.join(BASELINE_DIR,'compares.json'), JSON.stringify(d,null,2)); }

module.exports = { saveBaseline, compareWithBaseline, readBaselines, readCompares };
