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

/**
 * Sitemap-based URL validation tests
 *
 * These tests fetch URLs directly from the sitemaps and verify they resolve.
 * This catches issues where:
 * - URLs in sitemaps point to non-existent pages
 * - nginx routing doesn't serve mounted content correctly
 * - Static page generation produced broken links
 */

// Number of random URLs to sample from each sitemap
const SAMPLE_SIZE = 5;

// Helper to get random items from array
function getRandomItems<T>(array: T[], count: number): T[] {
  const shuffled = [...array].sort(() => 0.5 - Math.random());
  return shuffled.slice(0, Math.min(count, array.length));
}

// Parse URLs from sitemap XML
function parseUrlsFromSitemap(xml: string): string[] {
  const urls: string[] = [];
  const locRegex = /<loc>([^<]+)<\/loc>/g;
  let match;
  while ((match = locRegex.exec(xml)) !== null) {
    urls.push(match[1]);
  }
  return urls;
}

// Convert absolute URL to relative path for test requests
function toRelativePath(url: string): string {
  try {
    const parsed = new URL(url);
    return parsed.pathname;
  } catch {
    return url;
  }
}

test.describe('sitemap URL validation', () => {

  test('sitemap index loads and contains child sitemaps', async ({ page }) => {
    const response = await page.goto('/sitemap.xml');
    expect(response?.status()).toBe(200);

    const content = await page.content();
    expect(content).toContain('sitemapindex');
    expect(content).toContain('sitemap-candidates.xml');
  });

  test('candidates sitemap - sample URLs resolve', async ({ page }) => {
    // Fetch the sitemap
    const sitemapResponse = await page.goto('/candidates/sitemap-candidates.xml');

    // Sitemap might not exist yet - skip if 404
    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in candidates sitemap`);

    // Sample and test random URLs
    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('committees sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/committees/sitemap-committees.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in committees sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('parties sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/parties/sitemap-parties.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in parties sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('offices sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/offices/sitemap-offices.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in offices sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('districts sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/districts/sitemap-districts.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in districts sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('states sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/states/sitemap-states.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in states sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('elections sitemap - sample URLs resolve', async ({ page }) => {
    const sitemapResponse = await page.goto('/elections/sitemap-elections.xml');

    if (sitemapResponse?.status() === 404) {
      test.skip();
      return;
    }

    expect(sitemapResponse?.status()).toBe(200);
    const xml = await page.content();
    const urls = parseUrlsFromSitemap(xml);

    expect(urls.length).toBeGreaterThan(0);
    console.log(`Found ${urls.length} URLs in elections sitemap`);

    const sampleUrls = getRandomItems(urls, SAMPLE_SIZE);
    for (const url of sampleUrls) {
      const path = toRelativePath(url);
      console.log(`Testing: ${path}`);
      const response = await page.goto(path);
      expect(response?.status(), `Expected 200 for ${path}`).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

});
