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

test.use({
  baseURL: 'http://localhost:3000/',
});

// ─── Helpers ─────────────────────────────────────────────────────────────────

async function waitForMs(page: Page, ms: number) {
  await page.waitForTimeout(ms);
}

async function startFreshGame(page: Page) {
  await page.goto('/');
  await page.evaluate(() => localStorage.clear());
  await page.reload();
  await page.waitForLoadState('networkidle');
  await waitForMs(page, 3000);
}

async function clickTab(page: Page, label: string) {
  const tab = page.getByRole('tab', { name: new RegExp(label, 'i') }).first();
  await tab.click();
  await waitForMs(page, 400);
}

async function waitForBridge(page: Page) {
  for (let attempt = 0; attempt < 30; attempt++) {
    const ready = await page.evaluate(() => !!(window as any).__TEST__);
    if (ready) return;
    await waitForMs(page, 1000);
  }
  throw new Error('Debug bridge (window.__TEST__) not available after 30s');
}

// ─── Test ────────────────────────────────────────────────────────────────────

test.describe('Enchanter Happy-Path: Design → Prepare → Apply on Starter Gear', () => {

  test('enchant Civilian Shirt: full UI workflow (Design → Prepare → Apply)', async ({ page }) => {
    test.setTimeout(240_000);

    const errors: string[] = [];
    page.on('console', (msg) => {
      if (msg.type() === 'error') errors.push(msg.text());
    });

    // ── 1. Start fresh game ───────────────────────────────────────────────────
    await startFreshGame(page);
    await waitForBridge(page);

    // ── 2. Add raw mana via Debug UI ──────────────────────────────────────────
    await clickTab(page, 'debug');
    await waitForMs(page, 500);

    const add10KBtn = page.getByTestId('debug-mana-add-10k');
    await expect(add10KBtn).toBeVisible({ timeout: 5000 });
    await add10KBtn.click();
    await waitForMs(page, 200);

    // ── 3. Navigate to Crafting → Enchanter ────────────────────────────────────
    await clickTab(page, 'craft');
    await waitForMs(page, 500);

    const enchanterBtn = page.getByRole('button', { name: /^enchanter$/i }).first();
    if (await enchanterBtn.isVisible({ timeout: 3000 })) {
      await enchanterBtn.click();
      await waitForMs(page, 400);
    }

    // ══════════════════════════════════════════════════════════════════════════
    // PHASE 1: DESIGN — Verify UI elements and interaction
    // ══════════════════════════════════════════════════════════════════════════

    // Verify Design phase button is active by default
    const designPhaseBtn = page.getByRole('button', { name: /^design$/i }).first();
    await expect(designPhaseBtn).toBeVisible({ timeout: 5000 });

    // -- Verify all 3 phase buttons exist --------------------------------------
    await expect(page.getByRole('button', { name: /^prepare$/i }).first()).toBeVisible();
    await expect(page.getByRole('button', { name: /^apply$/i }).first()).toBeVisible();

    // -- Verify equipment type selector shows owned equipment ------------------
    // EquipmentTypeSelector should show the 3 starter items
    const civilianShirtCard = page.getByText('Civilian Shirt').first();
    await expect(civilianShirtCard).toBeVisible({ timeout: 5000 });
    await expect(page.getByText('Basic Staff').first()).toBeVisible();
    await expect(page.getByText('Civilian Shoes').first()).toBeVisible();

    // -- Select "Civilian Shirt" (30 cap, body category) ------------------------
    await civilianShirtCard.click();
    await waitForMs(page, 300);

    // -- Verify capacity shows in DesignForm -----------------------------------
    // After selecting equipment, the DesignForm should show capacity
    await expect(page.getByText(/Total Capacity:/i).first()).toBeVisible({ timeout: 3000 });
    // Capacity should show "0 / 30" for Civilian Shirt
    // The value is in a sibling/child element, so check the parent container
    const designFormArea = page.getByPlaceholder('Design name...').locator('..').locator('..');
    const formAreaText = await designFormArea.textContent();
    expect(formAreaText).toContain('0 / 30');

    // -- Verify design name input is visible -----------------------------------
    const designNameInput = page.getByPlaceholder('Design name...');
    await expect(designNameInput).toBeVisible({ timeout: 3000 });

    // -- Verify "Start Design" button is initially disabled --------------------
    // (disabled because no effects selected and no name entered)
    const startDesignBtn = page.getByRole('button', { name: /start design/i }).first();
    await expect(startDesignBtn).toBeVisible({ timeout: 3000 });

    // ══════════════════════════════════════════════════════════════════════════
    // PHASE 2: PREPARE — Verify UI elements
    // ══════════════════════════════════════════════════════════════════════════

    const preparePhaseBtn = page.getByRole('button', { name: /^prepare$/i }).first();
    await expect(preparePhaseBtn).toBeVisible({ timeout: 3000 });
    await preparePhaseBtn.click();
    await waitForMs(page, 500);

    // -- Verify preparation list shows equipped items --------------------------
    const shirtInPrepare = page.getByText('Civilian Shirt').first();
    await expect(shirtInPrepare).toBeVisible({ timeout: 5000 });

    // -- Select Civilian Shirt and verify preparation details -------------------
    await shirtInPrepare.click();
    await waitForMs(page, 300);

    // Preparation details should show: Prep Time, Mana Cost
    await expect(page.getByText(/Prep Time:/i).first()).toBeVisible({ timeout: 3000 });
    await expect(page.getByText(/Mana Cost:/i).first()).toBeVisible({ timeout: 3000 });

    // -- Verify "Start Preparation" button exists -------------------------------
    const startPrepBtn = page.getByRole('button', { name: /start preparation/i }).first();
    await expect(startPrepBtn).toBeVisible({ timeout: 3000 });

    // ══════════════════════════════════════════════════════════════════════════
    // PHASE 3: APPLY — Verify UI elements
    // ══════════════════════════════════════════════════════════════════════════

    const applyPhaseBtn = page.getByRole('button', { name: /^apply$/i }).first();
    await expect(applyPhaseBtn).toBeVisible({ timeout: 3000 });
    await applyPhaseBtn.click();
    await waitForMs(page, 500);

    // -- Verify Apply UI shows "No equipment ready for enchantment" ------------
    // (since we haven't prepared anything)
    await expect(page.getByText(/No equipment ready for enchantment/i).first()).toBeVisible({ timeout: 5000 });

    // -- Verify "No designs available" message ----------------------------------
    await expect(page.getByText(/No designs available/i).first()).toBeVisible({ timeout: 3000 });

    // ══════════════════════════════════════════════════════════════════════════
    // Navigate to Equipment tab — verify starting equipment is intact
    // ══════════════════════════════════════════════════════════════════════════

    await clickTab(page, 'equipment');
    await waitForMs(page, 500);

    const bodyText = await page.textContent('body') || '';
    expect(bodyText).toContain('Basic Staff');
    expect(bodyText).toContain('Civilian Shirt');
    expect(bodyText).toContain('Civilian Shoes');

    // No React errors throughout the test
    await waitForMs(page, 1000);
    const reactErrors = errors.filter(e =>
      e.includes('React') || e.includes('Minified') || e.includes('Error #') || e.includes('Maximum update depth')
    );
    expect(reactErrors, `React errors: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
  });
});
