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

// Wait timeout for async data loading (GraphQL browseEntities)
const DATA_LOAD_TIMEOUT = 15000;

// Entity index pages that use insertSearchUI from base.ts
const ENTITY_INDEX_PAGES = [
  { path: '/offices/', heading: /Offices/i },
  { path: '/candidates/', heading: /Candidates/i },
  { path: '/committees/', heading: /Committees/i },
  { path: '/districts/', heading: /Districts/i },
  { path: '/elections/', heading: /Election/i },
  { path: '/employers/', heading: /Employers/i },
  { path: '/individuals/', heading: /Individual/i },
  { path: '/parties/', heading: /Parties/i },
  { path: '/vendors/', heading: /Vendors/i },
  { path: '/counties/', heading: /Counties/i },
  { path: '/places/', heading: /Places/i },
  { path: '/precincts/', heading: /Precincts/i },
  { path: '/tracts/', heading: /Tracts/i },
  { path: '/postalcodes/', heading: /Postal/i },
  { path: '/blocks/', heading: /Blocks/i },
];

// All landing pages including special pages
const ALL_LANDING_PAGES = [
  ...ENTITY_INDEX_PAGES,
  { path: '/states/', heading: /States/i },
  { path: '/codesources/', heading: /Code Sources/i },
  { path: '/contributors/', heading: /Contributors/i },
  { path: '/datasources/', heading: /Data Sources/i },
  { path: '/', heading: /US Elections/i },
];

test.describe('landing page layout - no footer', () => {
  for (const { path, heading } of ALL_LANDING_PAGES) {
    test(`${path} has no footer element`, async ({ page }) => {
      await page.goto(path);
      await expect(page.locator('h1')).toContainText(heading);
      await expect(page.locator('footer')).toHaveCount(0);
    });
  }
});

test.describe('entity index layout - search UI above results', () => {
  for (const { path, heading } of ENTITY_INDEX_PAGES) {
    test(`${path} has no static search description in main`, async ({ page }) => {
      await page.goto(path);
      await expect(page.locator('h1')).toContainText(heading);

      // The <main> element should have no <section> or <p> children
      // (the search UI is injected by JS before <main>, not inside it)
      const mainSections = page.locator('main > section');
      await expect(mainSections).toHaveCount(0);
    });
  }

  test('offices - search container appears before main in DOM', async ({ page }) => {
    await page.goto('/offices/');
    await expect(page.locator('.entity-search-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });

    // Verify search container is a sibling before <main>, not inside it
    const searchIsBeforeMain = await page.evaluate(() => {
      const searchContainer = document.querySelector('.entity-search-container');
      const main = document.querySelector('main');
      if (!searchContainer || !main) return false;
      // compareDocumentPosition bit 4 = DOCUMENT_POSITION_FOLLOWING
      return (searchContainer.compareDocumentPosition(main) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
    });
    expect(searchIsBeforeMain).toBe(true);
  });

  test('candidates - search container appears before main in DOM', async ({ page }) => {
    await page.goto('/candidates/');
    await expect(page.locator('.entity-search-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });

    const searchIsBeforeMain = await page.evaluate(() => {
      const searchContainer = document.querySelector('.entity-search-container');
      const main = document.querySelector('main');
      if (!searchContainer || !main) return false;
      return (searchContainer.compareDocumentPosition(main) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
    });
    expect(searchIsBeforeMain).toBe(true);
  });
});
