/**
 * E2E Test: Visual Regression Testing
 * 
 * Tests for:
 * - Dashboard visual appearance
 * - Scenario Detail page
 * - Comparison page
 * - Reports page
 * - Dark/Light mode consistency
 */

import { test, expect } from '@playwright/test';
import { 
  navigateTo, 
  waitForLoading, 
  createScenarioViaAPI, 
  deleteScenarioViaAPI,
  startScenarioViaAPI,
  sendTestLogs,
  generateTestScenarioName,
  setDesktopViewport,
  setMobileViewport,
} from './utils/test-helpers';
import { newScenarioData } from './fixtures/test-scenarios';
import { testLogs } from './fixtures/test-logs';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Visual regression configuration
const BASELINE_DIR = path.join(__dirname, 'screenshots', 'baseline');
const ACTUAL_DIR = path.join(__dirname, 'screenshots', 'actual');
const DIFF_DIR = path.join(__dirname, 'screenshots', 'diff');

// Ensure directories exist
[BASELINE_DIR, ACTUAL_DIR, DIFF_DIR].forEach(dir => {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
});

// Threshold for visual differences (0.2 = 20%)
const VISUAL_THRESHOLD = 0.2;

let testScenarioId: string | null = null;

test.describe('Visual Regression - Dashboard', () => {
  test.beforeAll(async ({ request }) => {
    // Create a test scenario with data for better visuals
    const scenario = await createScenarioViaAPI(request, {
      ...newScenarioData,
      name: generateTestScenarioName('Visual Test'),
    });
    testScenarioId = scenario.id;

    await startScenarioViaAPI(request, scenario.id);
    await sendTestLogs(request, scenario.id, testLogs);
  });

  test.afterAll(async ({ request }) => {
    if (testScenarioId) {
      try {
        await request.post(`http://localhost:8000/api/v1/scenarios/${testScenarioId}/stop`);
      } catch {
        // Scenario might not be running
      }
      await deleteScenarioViaAPI(request, testScenarioId);
    }
  });

  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('dashboard should match baseline - desktop', async ({ page }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Wait for all content to stabilize
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('dashboard-desktop.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('dashboard should match baseline - mobile', async ({ page }) => {
    await setMobileViewport(page);
    await navigateTo(page, '/');
    await waitForLoading(page);

    // Wait for mobile layout to stabilize
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('dashboard-mobile.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('dashboard should match baseline - tablet', async ({ page }) => {
    await page.setViewportSize({ width: 768, height: 1024 });
    await navigateTo(page, '/');
    await waitForLoading(page);

    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('dashboard-tablet.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - Scenarios Page', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('scenarios list should match baseline', async ({ page }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('scenarios-list.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('scenarios list should be responsive - mobile', async ({ page }) => {
    await setMobileViewport(page);
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);

    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('scenarios-list-mobile.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - Scenario Detail', () => {
  test.beforeAll(async ({ request }) => {
    // Ensure we have a test scenario
    if (!testScenarioId) {
      const scenario = await createScenarioViaAPI(request, {
        ...newScenarioData,
        name: generateTestScenarioName('Visual Detail Test'),
      });
      testScenarioId = scenario.id;
      await startScenarioViaAPI(request, scenario.id);
      await sendTestLogs(request, scenario.id, testLogs);
    }
  });

  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('scenario detail should match baseline', async ({ page }) => {
    await navigateTo(page, `/scenarios/${testScenarioId}`);
    await waitForLoading(page);

    // Wait for metrics to load
    await page.waitForTimeout(2000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('scenario-detail.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('scenario detail should be responsive - mobile', async ({ page }) => {
    await setMobileViewport(page);
    await navigateTo(page, `/scenarios/${testScenarioId}`);
    await waitForLoading(page);

    await page.waitForTimeout(2000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('scenario-detail-mobile.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - 404 Page', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('404 page should match baseline', async ({ page }) => {
    await navigateTo(page, '/non-existent-page');
    await waitForLoading(page);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('404-page.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - Component Elements', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
    await navigateTo(page, '/');
    await waitForLoading(page);
  });

  test('header should match baseline', async ({ page }) => {
    const header = page.locator('header');
    await expect(header).toBeVisible();

    const screenshot = await header.screenshot();
    
    expect(screenshot).toMatchSnapshot('header.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('sidebar should match baseline', async ({ page }) => {
    const sidebar = page.locator('aside');
    await expect(sidebar).toBeVisible();

    const screenshot = await sidebar.screenshot();
    
    expect(screenshot).toMatchSnapshot('sidebar.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('stat cards should match baseline', async ({ page }) => {
    const statCards = page.locator('[class*="grid"] > div').first();
    await expect(statCards).toBeVisible();

    const screenshot = await statCards.screenshot();
    
    expect(screenshot).toMatchSnapshot('stat-card.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - Dark Mode', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('dashboard should render correctly in dark mode', async ({ page }) => {
    // Enable dark mode by adding class to html element
    await page.emulateMedia({ colorScheme: 'dark' });
    
    // Also add dark class to root element if the app uses class-based dark mode
    await page.evaluate(() => {
      document.documentElement.classList.add('dark');
    });

    await navigateTo(page, '/');
    await waitForLoading(page);
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('dashboard-dark.png', {
      threshold: VISUAL_THRESHOLD,
    });

    // Reset
    await page.emulateMedia({ colorScheme: 'light' });
    await page.evaluate(() => {
      document.documentElement.classList.remove('dark');
    });
  });

  test('scenarios list should render correctly in dark mode', async ({ page }) => {
    await page.emulateMedia({ colorScheme: 'dark' });
    await page.evaluate(() => {
      document.documentElement.classList.add('dark');
    });

    await navigateTo(page, '/scenarios');
    await waitForLoading(page);
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('scenarios-list-dark.png', {
      threshold: VISUAL_THRESHOLD,
    });

    // Reset
    await page.emulateMedia({ colorScheme: 'light' });
    await page.evaluate(() => {
      document.documentElement.classList.remove('dark');
    });
  });
});

test.describe('Visual Regression - Loading States', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('loading state should match baseline', async ({ page }) => {
    // Navigate and immediately capture before loading completes
    await page.goto('/scenarios');
    
    // Wait just a moment to catch loading state
    await page.waitForTimeout(100);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot('loading-state.png', {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

test.describe('Visual Regression - Cross-browser', () => {
  test.beforeEach(async ({ page }) => {
    await setDesktopViewport(page);
  });

  test('dashboard renders consistently across browsers', async ({ page, browserName }) => {
    await navigateTo(page, '/');
    await waitForLoading(page);
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot(`dashboard-${browserName}.png`, {
      threshold: VISUAL_THRESHOLD,
    });
  });

  test('scenarios list renders consistently across browsers', async ({ page, browserName }) => {
    await navigateTo(page, '/scenarios');
    await waitForLoading(page);
    await page.waitForTimeout(1000);

    const screenshot = await page.screenshot({ fullPage: true });
    
    expect(screenshot).toMatchSnapshot(`scenarios-${browserName}.png`, {
      threshold: VISUAL_THRESHOLD,
    });
  });
});

// Helper to update baseline screenshots
test.describe('Visual Regression - Baseline Management', () => {
  test.skip(process.env.UPDATE_BASELINE !== 'true', 'Only run when updating baselines');

  test('update all baseline screenshots', async ({ page }) => {
    // This test runs only when UPDATE_BASELINE is set
    // It generates new baseline screenshots

    const pages = [
      { path: '/', name: 'dashboard-desktop' },
      { path: '/scenarios', name: 'scenarios-list' },
    ];

    for (const { path: pagePath, name } of pages) {
      await navigateTo(page, pagePath);
      await waitForLoading(page);
      await page.waitForTimeout(1000);

      const screenshot = await page.screenshot({ fullPage: true });
      
      // Save as baseline
      const baselinePath = path.join(BASELINE_DIR, `${name}.png`);
      fs.writeFileSync(baselinePath, screenshot);
    }
  });
});
