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

// Entity section tests verify generated content is properly served

// 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));
}

// Helper to convert full URL to relative path
function toRelativePath(url: string): string {
  try {
    const parsed = new URL(url);
    return parsed.pathname;
  } catch {
    return url;
  }
}

// Selector for entity links - works with:
// - base.ts modules (OpenSearch): .entity-search-result
// - standalone GraphQL modules: .district-result, .state-result, etc.
// - legacy: .entity-list a
const ENTITY_LINK_SELECTOR = '.entity-search-result, .entity-list a, .district-result, .state-result, .county-result, .place-result, .postal-result, .precinct-result';

test.describe('us.elect.info entity sections', () => {

  test('candidates section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/candidates/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Candidates/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('committees section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/committees/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Committees/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('parties section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/parties/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Parties/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('offices section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/offices/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Offices/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('districts section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/districts/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Districts/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('states section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/states/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/States/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });

  test('elections section - index and random pages', async ({ page }) => {
    const indexResponse = await page.goto('/elections/');
    expect(indexResponse?.status()).toBe(200);
    await expect(page.locator('h1')).toContainText(/Election/i);

    const links = await page.locator(ENTITY_LINK_SELECTOR).all();
    expect(links.length).toBeGreaterThan(0);

    const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
    const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);

    for (const href of randomLinks) {
      const entityResponse = await page.goto(toRelativePath(href));
      expect(entityResponse?.status()).toBe(200);
      await expect(page.locator('h1')).toBeVisible();
    }
  });
});
