// @ts-check
/**
 * Geography demos — comprehensive page load + interaction tests.
 */
const { test, expect } = require('playwright/test');
const { loadPage, trackErrors } = require('./helpers');

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
async function expectIsland(page, pattern) {
  const island = page.locator(`[data-sx-island*="${pattern}"]`);
  await expect(island).toBeVisible({ timeout: 8000 });
  return island;
}


// ===========================================================================
// Geography section index pages
// ===========================================================================

test.describe('Geography sections', () => {
  let t;
  test.beforeEach(({ page }) => { t = trackErrors(page); });
  test.afterEach(() => { expect(t.errors()).toEqual([]); });

  const sections = [
    ['(geography)', 'Geography'],
    ['(geography.(reactive))', 'Reactive'],
    ['(geography.(hypermedia))', 'Hypermedia'],
    ['(geography.(marshes))', 'Marshes'],
    ['(geography.(scopes))', 'Scopes'],
    ['(geography.(cek))', 'CEK'],
    ['(geography.(isomorphism))', 'Isomorphism'],
    ['(geography.(spreads))', 'Spreads'],
    ['(geography.(provide))', 'Provide'],
  ];

  for (const [path, text] of sections) {
    test(`${path} loads`, async ({ page }) => {
      await loadPage(page, path);
      const root = page.locator('#sx-root');
      expect(await root.textContent()).toContain(text);
    });
  }
});


// ===========================================================================
// Reactive demos — each test is isolated but fast (cached)
// ===========================================================================

test.describe('Reactive demos', () => {
  let t;
  test.beforeEach(({ page }) => { t = trackErrors(page); });
  test.afterEach(() => { expect(t.errors()).toEqual([]); });

  const demos = [
    ['counter', 'counter'],
    ['temperature', 'temperature'],
    ['stopwatch', 'stopwatch'],
    ['input-binding', 'input-binding'],
    ['dynamic-class', 'dynamic-class'],
    ['reactive-list', 'reactive-list'],
    ['stores', 'store-writer'],
    ['refs', 'refs'],
    ['portal', 'portal'],
    ['resource', null],
    ['imperative', null],
    ['transition', null],
    ['error-boundary', null],
    ['event-bridge-demo', null],
    ['defisland', null],
    ['coverage', null],
  ];

  for (const [slug, islandPattern] of demos) {
    test(`${slug} loads`, async ({ page }) => {
      await loadPage(page, `(geography.(reactive.(examples.${slug})))`);
      if (islandPattern) await expectIsland(page, islandPattern);
    });
  }

  test('counter: buttons change count', async ({ page }) => {
    await loadPage(page, '(geography.(reactive.(examples.counter)))');
    const el = await expectIsland(page, 'counter');
    const buttons = el.locator('button');
    await expect(buttons).toHaveCount(2);
    const textBefore = await el.textContent();
    await buttons.last().click();
    await page.waitForTimeout(300);
    expect(await el.textContent()).not.toBe(textBefore);
  });

  test('temperature: buttons change conversion', async ({ page }) => {
    await loadPage(page, '(geography.(reactive.(examples.temperature)))');
    const el = await expectIsland(page, 'temperature');
    const buttons = el.locator('button');
    if (await buttons.count() >= 2) {
      const textBefore = await el.textContent();
      await buttons.last().click();
      await page.waitForTimeout(300);
      expect(await el.textContent()).not.toBe(textBefore);
    }
  });

  test('stores: shared state across islands', async ({ page }) => {
    await loadPage(page, '(geography.(reactive.(examples.stores)))');
    await expect(page.locator('[data-sx-island*="store-reader"]')).toBeVisible({ timeout: 8000 });
    await expect(page.locator('[data-sx-island*="store-writer"]')).toBeVisible({ timeout: 8000 });
  });
});


// ===========================================================================
// Hypermedia demos
// ===========================================================================

test.describe('Hypermedia demos', () => {
  let t;
  test.beforeEach(({ page }) => { t = trackErrors(page); });
  test.afterEach(() => { expect(t.errors()).toEqual([]); });

  const demos = [
    'click-to-load', 'form-submission', 'polling', 'delete-row', 'edit-row',
    'tabs', 'active-search', 'inline-validation', 'lazy-loading',
    'infinite-scroll', 'select-filter', 'loading-states', 'dialogs',
    'oob-swaps', 'bulk-update', 'animations', 'inline-edit', 'progress-bar',
    'swap-positions', 'sync-replace', 'keyboard-shortcuts', 'json-encoding',
    'put-patch', 'retry', 'reset-on-submit', 'value-select', 'vals-and-headers',
  ];

  for (const slug of demos) {
    test(`${slug} loads`, async ({ page }) => {
      await loadPage(page, `(geography.(hypermedia.(example.${slug})))`);
    });
  }
});


// ===========================================================================
// Cross-navigation reactivity
// ===========================================================================

test('counter → temperature → counter: all stay reactive', async ({ page }) => {
  const t = trackErrors(page);
  await loadPage(page, '(geography.(reactive.(examples.counter)))');

  let el = await expectIsland(page, 'counter');
  let buttons = el.locator('button');
  let before = await el.textContent();
  await buttons.last().click();
  await page.waitForTimeout(300);
  expect(await el.textContent()).not.toBe(before);

  // SPA navigate to temperature
  const tempLink = page.locator('a[href*="temperature"]').first();
  if (await tempLink.count() > 0) {
    await tempLink.click();
    el = await expectIsland(page, 'temperature');
    buttons = el.locator('button');
    if (await buttons.count() >= 2) {
      before = await el.textContent();
      await buttons.last().click();
      await page.waitForTimeout(300);
      expect(await el.textContent()).not.toBe(before);
    }
  }

  // SPA navigate back to counter
  const counterLink = page.locator('a[href*="counter"]').first();
  if (await counterLink.count() > 0) {
    await counterLink.click();
    el = await expectIsland(page, 'counter');
    buttons = el.locator('button');
    before = await el.textContent();
    await buttons.last().click();
    await page.waitForTimeout(300);
    expect(await el.textContent()).not.toBe(before);
  }

  expect(t.errors()).toEqual([]);
});


// ===========================================================================
// Other geography pages
// ===========================================================================

test.describe('Other geography pages', () => {
  let t;
  test.beforeEach(({ page }) => { t = trackErrors(page); });
  test.afterEach(() => { expect(t.errors()).toEqual([]); });

  const pages = [
    '(geography.(cek.demo))', '(geography.(cek.content))', '(geography.(cek.freeze))',
    '(geography.(marshes.hypermedia-feeds))', '(geography.(marshes.on-settle))',
    '(geography.(marshes.server-signals))', '(geography.(marshes.signal-triggers))',
    '(geography.(marshes.view-transform))',
    '(geography.(isomorphism))',
  ];

  for (const path of pages) {
    test(`${path} loads`, async ({ page }) => {
      await loadPage(page, path);
    });
  }
});

test.describe('Reference pages', () => {
  let t;
  test.beforeEach(({ page }) => { t = trackErrors(page); });
  test.afterEach(() => { expect(t.errors()).toEqual([]); });

  for (const sub of ['attributes', 'events', 'headers', 'js-api']) {
    test(`${sub} loads`, async ({ page }) => {
      await loadPage(page, `(geography.(hypermedia.(reference.${sub})))`);
    });
  }
});
