import { test, expect } from '@playwright/test';

/**
 * Performance Testing Suite
 * Tests Core Web Vitals and page load performance
 */

const PERFORMANCE_THRESHOLDS = {
  LCP: 2500,  // Largest Contentful Paint (ms)
  FID: 100,   // First Input Delay (ms)
  CLS: 0.1,   // Cumulative Layout Shift (score)
  FCP: 1800,  // First Contentful Paint (ms)
  TTFB: 800,  // Time to First Byte (ms)
  TTI: 3800,  // Time to Interactive (ms)
};

test.describe('Performance Metrics', () => {
  test.beforeEach(async ({ page }) => {
    // Enable performance metrics collection
    await page.goto('/', { waitUntil: 'networkidle' });
  });

  test('should meet Core Web Vitals thresholds on home page (EN)', async ({ page }) => {
    await page.goto('/en', { waitUntil: 'networkidle' });

    // Measure performance metrics
    const performanceMetrics = await page.evaluate(() => {
      return new Promise((resolve) => {
        const metrics: Record<string, number> = {};

        // Collect Web Vitals
        if ('PerformanceObserver' in window) {
          // Largest Contentful Paint
          new PerformanceObserver((list) => {
            const entries = list.getEntries();
            const lastEntry = entries[entries.length - 1] as any;
            metrics.LCP = lastEntry.renderTime || lastEntry.loadTime;
          }).observe({ type: 'largest-contentful-paint', buffered: true });

          // First Contentful Paint
          const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0] as any;
          if (fcpEntry) {
            metrics.FCP = fcpEntry.startTime;
          }

          // Time to First Byte
          const navigationEntry = performance.getEntriesByType('navigation')[0] as any;
          if (navigationEntry) {
            metrics.TTFB = navigationEntry.responseStart;
          }

          // Cumulative Layout Shift
          let clsValue = 0;
          new PerformanceObserver((list) => {
            for (const entry of list.getEntries() as any[]) {
              if (!entry.hadRecentInput) {
                clsValue += entry.value;
              }
            }
            metrics.CLS = clsValue;
          }).observe({ type: 'layout-shift', buffered: true });
        }

        setTimeout(() => resolve(metrics), 3000);
      });
    });

    console.log('📊 Performance Metrics (EN Home):', performanceMetrics);

    // Assertions
    const metrics = performanceMetrics as Record<string, number>;
    if (metrics.LCP) {
      expect(metrics.LCP, `LCP should be under ${PERFORMANCE_THRESHOLDS.LCP}ms`).toBeLessThan(PERFORMANCE_THRESHOLDS.LCP);
    }
    if (metrics.FCP) {
      expect(metrics.FCP, `FCP should be under ${PERFORMANCE_THRESHOLDS.FCP}ms`).toBeLessThan(PERFORMANCE_THRESHOLDS.FCP);
    }
    if (metrics.TTFB) {
      expect(metrics.TTFB, `TTFB should be under ${PERFORMANCE_THRESHOLDS.TTFB}ms`).toBeLessThan(PERFORMANCE_THRESHOLDS.TTFB);
    }
    if (metrics.CLS !== undefined) {
      expect(metrics.CLS, `CLS should be under ${PERFORMANCE_THRESHOLDS.CLS}`).toBeLessThan(PERFORMANCE_THRESHOLDS.CLS);
    }
  });

  test('should meet performance thresholds on Arabic home page', async ({ page }) => {
    await page.goto('/ar', { waitUntil: 'networkidle' });

    const performanceMetrics = await page.evaluate(() => {
      return new Promise((resolve) => {
        const metrics: Record<string, number> = {};

        if ('PerformanceObserver' in window) {
          new PerformanceObserver((list) => {
            const entries = list.getEntries();
            const lastEntry = entries[entries.length - 1] as any;
            metrics.LCP = lastEntry.renderTime || lastEntry.loadTime;
          }).observe({ type: 'largest-contentful-paint', buffered: true });

          const fcpEntry = performance.getEntriesByName('first-contentful-paint')[0] as any;
          if (fcpEntry) {
            metrics.FCP = fcpEntry.startTime;
          }

          const navigationEntry = performance.getEntriesByType('navigation')[0] as any;
          if (navigationEntry) {
            metrics.TTFB = navigationEntry.responseStart;
          }
        }

        setTimeout(() => resolve(metrics), 3000);
      });
    });

    console.log('📊 Performance Metrics (AR Home):', performanceMetrics);

    const metrics = performanceMetrics as Record<string, number>;
    if (metrics.LCP) {
      expect(metrics.LCP).toBeLessThan(PERFORMANCE_THRESHOLDS.LCP);
    }
    if (metrics.FCP) {
      expect(metrics.FCP).toBeLessThan(PERFORMANCE_THRESHOLDS.FCP);
    }
  });

  test('should have fast navigation between pages', async ({ page }) => {
    await page.goto('/en', { waitUntil: 'networkidle' });

    // Measure navigation performance
    const navigationStart = Date.now();

    // Click a navigation link
    await page.click('a[href*="/demo"]');
    await page.waitForURL('**/demo');

    const navigationEnd = Date.now();
    const navigationTime = navigationEnd - navigationStart;

    console.log('⚡ Navigation Time (EN → Demo):', navigationTime, 'ms');

    // Navigation should feel instant (< 500ms perceived)
    expect(navigationTime, 'Client-side navigation should be fast').toBeLessThan(1000);
  });

  test('should have optimized bundle sizes', async ({ page }) => {
    const response = await page.goto('/en');

    // Check JavaScript bundle sizes
    const jsResources = await page.evaluate(() => {
      return performance.getEntriesByType('resource')
        .filter((entry: any) => entry.name.includes('.js'))
        .map((entry: any) => ({
          name: entry.name.split('/').pop(),
          size: entry.transferSize,
          duration: entry.duration,
        }));
    });

    console.log('📦 JavaScript Resources:', jsResources);

    // Check total JS size
    const totalJsSize = jsResources.reduce((sum: number, resource: any) => sum + (resource.size || 0), 0);
    console.log('📦 Total JS Size:', (totalJsSize / 1024).toFixed(2), 'KB');

    // Total JS should be under 300KB (compressed)
    expect(totalJsSize, 'Total JavaScript size should be optimized').toBeLessThan(300000);
  });

  test('should load images efficiently with lazy loading', async ({ page }) => {
    await page.goto('/en', { waitUntil: 'networkidle' });

    // Check for images in viewport
    const imageMetrics = await page.evaluate(() => {
      const images = Array.from(document.querySelectorAll('img'));
      return images.map(img => ({
        src: img.src,
        loading: img.loading,
        width: img.width,
        height: img.height,
        decoded: img.complete,
      }));
    });

    console.log('🖼️  Image Loading Strategy:', imageMetrics);

    // Check that images use next/image optimizations
    const lazyImages = imageMetrics.filter((img: any) => img.loading === 'lazy');
    console.log(`✅ Lazy loaded images: ${lazyImages.length}/${imageMetrics.length}`);

    // Most images should use lazy loading (except above-fold)
    expect(lazyImages.length).toBeGreaterThan(0);
  });

  test('should have effective caching headers', async ({ page }) => {
    const response = await page.goto('/en');

    const cacheControl = response?.headers()['cache-control'];
    console.log('💾 Cache-Control Header:', cacheControl);

    // Static assets should have caching
    const staticResponse = await page.goto('/_next/static/css/app.css').catch(() => null);
    if (staticResponse) {
      const staticCache = staticResponse.headers()['cache-control'];
      console.log('📦 Static Asset Cache:', staticCache);
      expect(staticCache).toContain('max-age');
    }
  });
});

test.describe('Page Load Performance', () => {
  test('should load demo page quickly', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('/en/demo', { waitUntil: 'networkidle' });
    const loadTime = Date.now() - startTime;

    console.log('⏱️  Demo Page Load Time:', loadTime, 'ms');

    // Page should load in under 3 seconds
    expect(loadTime, 'Demo page load time').toBeLessThan(3000);
  });

  test('should load signup page quickly', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('/en/signup', { waitUntil: 'networkidle' });
    const loadTime = Date.now() - startTime;

    console.log('⏱️  Signup Page Load Time:', loadTime, 'ms');

    expect(loadTime, 'Signup page load time').toBeLessThan(3000);
  });

  test('should load pricing page quickly', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('/ar/pricing', { waitUntil: 'networkidle' });
    const loadTime = Date.now() - startTime;

    console.log('⏱️  Pricing Page Load Time (AR):', loadTime, 'ms');

    expect(loadTime, 'Pricing page load time').toBeLessThan(3000);
  });

  test('should load ai-voice-agents page quickly', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('/en/ai-voice-agents', { waitUntil: 'networkidle' });
    const loadTime = Date.now() - startTime;

    console.log('⏱️  AI Voice Agents Page Load Time:', loadTime, 'ms');

    expect(loadTime, 'AI Voice Agents page load time').toBeLessThan(3000);
  });
});
