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

/**
 * Core Web Vitals Performance Tests
 * Tests LCP, FID, CLS, FCP, and TTFB for key pages
 */

interface WebVitals {
  lcp: number;
  fid: number;
  cls: number;
  fcp: number;
  ttfb: number;
}

async function measureWebVitals(page: any): Promise<WebVitals> {
  return await page.evaluate(() => {
    return new Promise<WebVitals>((resolve) => {
      const metrics: Partial<WebVitals> = {};

      // Measure LCP (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({ entryTypes: ['largest-contentful-paint'] });

      // Measure CLS (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({ entryTypes: ['layout-shift'] });

      // Measure FCP (First Contentful Paint)
      new PerformanceObserver((list) => {
        const entries = list.getEntries();
        const fcpEntry = entries[0] as any;
        metrics.fcp = fcpEntry.startTime;
      }).observe({ entryTypes: ['paint'] });

      // Get navigation timing for TTFB
      const navTiming = performance.getEntriesByType('navigation')[0] as any;
      if (navTiming) {
        metrics.ttfb = navTiming.responseStart - navTiming.requestStart;
      }

      // Simulate FID (First Input Delay) - in real scenario this would be user interaction
      metrics.fid = 0; // Will be measured during interaction tests

      // Wait for metrics to stabilize
      setTimeout(() => {
        resolve({
          lcp: metrics.lcp || 0,
          fid: metrics.fid || 0,
          cls: metrics.cls || 0,
          fcp: metrics.fcp || 0,
          ttfb: metrics.ttfb || 0,
        });
      }, 5000);
    });
  });
}

test.describe('Core Web Vitals - Homepage', () => {
  test('English homepage meets performance thresholds', async ({ page }) => {
    await page.goto('http://localhost:9000/en');
    await page.waitForLoadState('networkidle');

    const vitals = await measureWebVitals(page);

    console.log('Homepage (EN) Web Vitals:', vitals);

    // LCP should be < 2.5s (Good)
    expect(vitals.lcp).toBeLessThan(2500);

    // CLS should be < 0.1 (Good)
    expect(vitals.cls).toBeLessThan(0.1);

    // FCP should be < 1.8s (Good)
    expect(vitals.fcp).toBeLessThan(1800);

    // TTFB should be < 600ms
    expect(vitals.ttfb).toBeLessThan(600);
  });

  test('Arabic homepage meets performance thresholds', async ({ page }) => {
    await page.goto('http://localhost:9000/ar');
    await page.waitForLoadState('networkidle');

    const vitals = await measureWebVitals(page);

    console.log('Homepage (AR) Web Vitals:', vitals);

    expect(vitals.lcp).toBeLessThan(2500);
    expect(vitals.cls).toBeLessThan(0.1);
    expect(vitals.fcp).toBeLessThan(1800);
    expect(vitals.ttfb).toBeLessThan(600);
  });

  test('Homepage load time is under 3 seconds', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    console.log(`Homepage load time: ${loadTime}ms`);
    expect(loadTime).toBeLessThan(3000);
  });
});

test.describe('Core Web Vitals - Critical Pages', () => {
  test('Pricing page performance', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en/pricing');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    const vitals = await measureWebVitals(page);

    console.log('Pricing Page Web Vitals:', vitals);
    console.log(`Pricing page load time: ${loadTime}ms`);

    expect(vitals.lcp).toBeLessThan(2500);
    expect(vitals.cls).toBeLessThan(0.1);
    expect(loadTime).toBeLessThan(3000);
  });

  test('Demo booking page performance', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en/demo');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    const vitals = await measureWebVitals(page);

    console.log('Demo Page Web Vitals:', vitals);
    console.log(`Demo page load time: ${loadTime}ms`);

    expect(vitals.lcp).toBeLessThan(2500);
    expect(vitals.cls).toBeLessThan(0.1);
    expect(loadTime).toBeLessThan(3000);
  });

  test('Login page performance', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en/login');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    const vitals = await measureWebVitals(page);

    console.log('Login Page Web Vitals:', vitals);
    console.log(`Login page load time: ${loadTime}ms`);

    expect(vitals.lcp).toBeLessThan(2000); // Login should be very fast
    expect(vitals.cls).toBeLessThan(0.1);
    expect(loadTime).toBeLessThan(2000);
  });

  test('Signup page performance', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en/signup');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    const vitals = await measureWebVitals(page);

    console.log('Signup Page Web Vitals:', vitals);
    console.log(`Signup page load time: ${loadTime}ms`);

    expect(vitals.lcp).toBeLessThan(2000);
    expect(vitals.cls).toBeLessThan(0.1);
    expect(loadTime).toBeLessThan(2000);
  });

  test('Blog listing page performance', async ({ page }) => {
    const startTime = Date.now();
    await page.goto('http://localhost:9000/en/blog');
    await page.waitForLoadState('networkidle');
    const loadTime = Date.now() - startTime;

    const vitals = await measureWebVitals(page);

    console.log('Blog Page Web Vitals:', vitals);
    console.log(`Blog page load time: ${loadTime}ms`);

    expect(vitals.lcp).toBeLessThan(2500);
    expect(vitals.cls).toBeLessThan(0.1);
    expect(loadTime).toBeLessThan(3000);
  });
});

test.describe('Core Web Vitals - Dynamic Service Pages', () => {
  const testPages = [
    { location: 'qatar', service: 'medical-appointment-scheduling', lang: 'en' },
    { location: 'dubai', service: 'healthcare-chatbot', lang: 'en' },
    { location: 'riyadh', service: 'patient-intake', lang: 'ar' },
    { location: 'kuwait', service: 'appointment-reminders', lang: 'en' },
    { location: 'bahrain', service: 'virtual-receptionist', lang: 'ar' },
  ];

  for (const { location, service, lang } of testPages) {
    test(`Service page ${location}/${service} (${lang}) performance`, async ({ page }) => {
      const url = `http://localhost:9000/${lang}/${location}/${service}`;
      const startTime = Date.now();

      await page.goto(url);
      await page.waitForLoadState('networkidle');
      const loadTime = Date.now() - startTime;

      const vitals = await measureWebVitals(page);

      console.log(`Service Page (${location}/${service}) Web Vitals:`, vitals);
      console.log(`Load time: ${loadTime}ms`);

      // Service pages should be fast (ISR cached)
      expect(vitals.lcp).toBeLessThan(1500);
      expect(vitals.cls).toBeLessThan(0.1);
      expect(loadTime).toBeLessThan(2000);
    });
  }
});

test.describe('Page Weight and Resource Analysis', () => {
  test('Homepage total page weight', async ({ page }) => {
    await page.goto('http://localhost:9000/en');
    await page.waitForLoadState('networkidle');

    const resources = await page.evaluate(() => {
      const entries = performance.getEntriesByType('resource') as PerformanceResourceTiming[];
      return entries.map(entry => ({
        name: entry.name,
        size: entry.transferSize || 0,
        type: entry.initiatorType,
      }));
    });

    const totalSize = resources.reduce((sum, r) => sum + r.size, 0);
    const jsSize = resources.filter(r => r.name.endsWith('.js')).reduce((sum, r) => sum + r.size, 0);
    const cssSize = resources.filter(r => r.name.endsWith('.css')).reduce((sum, r) => sum + r.size, 0);
    const imageSize = resources.filter(r => r.type === 'img').reduce((sum, r) => sum + r.size, 0);

    console.log('Page Weight Analysis:');
    console.log(`Total: ${(totalSize / 1024).toFixed(2)} KB`);
    console.log(`JavaScript: ${(jsSize / 1024).toFixed(2)} KB`);
    console.log(`CSS: ${(cssSize / 1024).toFixed(2)} KB`);
    console.log(`Images: ${(imageSize / 1024).toFixed(2)} KB`);

    // Total page weight should be < 1MB (without large images)
    expect(totalSize).toBeLessThan(1024 * 1024);

    // JS bundle should be < 300KB (gzipped)
    expect(jsSize).toBeLessThan(300 * 1024);

    // CSS should be < 100KB (gzipped)
    expect(cssSize).toBeLessThan(100 * 1024);
  });

  test('Images use optimization', async ({ page }) => {
    await page.goto('http://localhost:9000/en');
    await page.waitForLoadState('networkidle');

    const images = await page.locator('img').all();
    const imageData = await Promise.all(
      images.map(async (img) => ({
        src: await img.getAttribute('src'),
        loading: await img.getAttribute('loading'),
      }))
    );

    console.log(`Total images found: ${imageData.length}`);

    // Check that images use Next.js Image component (src starts with /_next/image)
    const optimizedImages = imageData.filter(
      img => img.src?.includes('/_next/image') || img.src?.startsWith('data:')
    );

    console.log(`Optimized images: ${optimizedImages.length}`);
    console.log(`Lazy-loaded images: ${imageData.filter(img => img.loading === 'lazy').length}`);

    // Most images should be optimized (allow some external images)
    expect(optimizedImages.length).toBeGreaterThan(imageData.length * 0.7);
  });
});
