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

/* eslint-disable @typescript-eslint/no-explicit-any */
declare global {
  interface Window {
    __game: any;
  }
}

function trackErrors(page: Page): string[] {
  const errors: string[] = [];
  page.on('console', (m) => {
    if (m.type() === 'error') errors.push(m.text());
  });
  page.on('pageerror', (e) => errors.push(String(e)));
  return errors;
}

test.describe('Short Stack', () => {
  test('title → start → guest → assemble → cook → serve → coins', async ({ page }) => {
    const errors = trackErrors(page);
    await page.goto('/');

    await expect(page.getByTestId('start')).toBeVisible();
    await page.getByTestId('start').tap();
    await page.getByTestId('startday').tap();
    await page.waitForFunction(() => window.__game?.phase === 'playing');

    // a guest arrives and settles at the counter
    await page.waitForFunction(
      () => window.__game.guests.some((g: any) => g.state === 'waiting'),
      undefined,
      { timeout: 15_000 },
    );
    const slot: number = await page.evaluate(
      () => window.__game.guests.find((g: any) => g.state === 'waiting').slot,
    );

    // tap the order bubble → cooking panel opens
    await page.locator(`.bubble[data-slot="${slot}"]`).tap();
    await page.waitForFunction(() => window.__game.activeRecipe.length > 0);

    // assemble in order
    const ings: string[] = await page.evaluate(() => window.__game.activeRecipe);
    expect(ings.length).toBeGreaterThanOrEqual(2);
    for (const ing of ings) {
      await page.locator(`button.ing[data-ing="${ing}"]`).tap();
    }

    // cook timing bar, then serve
    await page.getByTestId('cooktap').tap();
    await page.getByTestId('serve').tap();

    await page.waitForFunction(() => window.__game.coins > 0);
    expect(await page.evaluate(() => window.__game.coins)).toBeGreaterThan(0);
    expect(await page.evaluate(() => window.__game.guests.some((g: any) => g.state === 'leaving-happy'))).toBe(
      true,
    );
    expect(errors).toEqual([]);
  });

  test('serveTest() hook serves a guest programmatically', async ({ page }) => {
    const errors = trackErrors(page);
    await page.goto('/');
    await page.waitForFunction(() => !!window.__game);
    await page.evaluate(() => window.__game.start()); // title → dayintro
    await page.evaluate(() => window.__game.start()); // dayintro → playing
    await page.waitForFunction(() => window.__game.phase === 'playing');
    await page.waitForFunction(
      () => window.__game.guests.some((g: any) => g.state === 'waiting'),
      undefined,
      { timeout: 15_000 },
    );
    const earned: number = await page.evaluate(() => window.__game.serveTest());
    expect(earned).toBeGreaterThan(0);
    expect(await page.evaluate(() => window.__game.coins)).toBe(earned);
    expect(errors).toEqual([]);
  });
});
