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

// Use the deployed production URL
test.use({
  baseURL: 'https://manaloop.tailf367e3.ts.net/',
});

// Helper: Clear localStorage and reload for fresh game
async function startFreshGame(page: Page) {
  await page.goto('/');
  await page.evaluate(() => localStorage.clear());
  await page.reload();
  await page.waitForLoadState('networkidle');
}

// Helper: Run debug command via console
async function runDebug(page: Page, cmd: string) {
  await page.evaluate((c) => {
    // @ts-expect-error - debug function on window
    if (typeof window.__debug === 'function') window.__debug(c);
  }, cmd);
}

// Helper: Wait for game to tick a few times
async function waitForTicks(page: Page, ms = 1000) {
  await page.waitForTimeout(ms);
}

test.describe('Mana Loop - Comprehensive Playtest', () => {

  // =========================================================================
  // SECTION 1: Basic UI & Starting State
  // =========================================================================
  test.describe('1 - Basic UI & Starting State', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('game loads without console errors', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 2000);
      const reactErrors = errors.filter(e =>
        e.includes('React') || e.includes('Minified') || e.includes('Error #') || e.includes('Maximum update depth')
      );
      expect(reactErrors, `React errors found: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
    });

    test('ManaDisplay is visible and shows Transference mana', async ({ page }) => {
      await waitForTicks(page, 500);
      // Mana display should show Transference mana pool
      const manaDisplay = page.locator('text=Transference').first();
      await expect(manaDisplay).toBeVisible({ timeout: 10000 });
    });

    test('TimeDisplay shows correct starting time', async ({ page }) => {
      await waitForTicks(page, 500);
      // Should start at day 1
      const bodyText = await page.textContent('body');
      expect(bodyText).toContain('Day 1');
    });

    test('Activity log is present and shows start message', async ({ page }) => {
      await waitForTicks(page, 500);
      const bodyText = await page.textContent('body');
      // Activity log should have some content
      expect(bodyText).toBeTruthy();
    });
  });

  // =========================================================================
  // SECTION 2 - Stats Tab (Known bugs #208 and #210)
  // =========================================================================
  test.describe('2 - Stats Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Stats tab', async ({ page }) => {
      await waitForTicks(page, 500);
      const statsTab = page.getByRole('tab', { name: /stats/i });
      if (await statsTab.isVisible()) {
        await statsTab.click();
        await waitForTicks(page, 300);
        // Should not crash
        const bodyText = await page.textContent('body');
        expect(bodyText).toBeTruthy();
      }
    });

    test('KNOWN BUG #208: Meditation multiplier shows 0x instead of 1x', async ({ page }) => {
      await waitForTicks(page, 500);
      const statsTab = page.getByRole('tab', { name: /stats/i });
      if (await statsTab.isVisible()) {
        await statsTab.click();
        await waitForTicks(page, 500);
        const bodyText = await page.textContent('body') || '';
        // The bug: Meditation Multiplier shows "0x" instead of "1.00x"
        // This test documents the current state
        if (bodyText.includes('Meditation')) {
          console.log('STATS: Meditation text found, checking value...');
          // Capture the actual state for reporting
        }
      }
    });

    test('KNOWN BUG #208: Effective Regen shows 0/hr', async ({ page }) => {
      await waitForTicks(page, 500);
      const statsTab = page.getByRole('tab', { name: /stats/i });
      if (await statsTab.isVisible()) {
        await statsTab.click();
        await waitForTicks(page, 500);
        const bodyText = await page.textContent('body') || '';
        if (bodyText.includes('Effective Regen') || bodyText.includes('Base Regen')) {
          console.log('STATS: Regen stats found');
        }
      }
    });

    test('KNOWN BUG #210: Total Max Mana ignores discipline bonuses', async ({ page }) => {
      await waitForTicks(page, 500);
      // Navigate to stats
      const statsTab = page.getByRole('tab', { name: /stats/i });
      if (await statsTab.isVisible()) {
        await statsTab.click();
        await waitForTicks(page, 300);
        // Check if Total Max Mana is shown
        const bodyText = await page.textContent('body') || '';
        console.log('STATS: Max Mana section - checking for discipline bonus inclusion');
      }
    });
  });

  // =========================================================================
  // SECTION 3 - Spire/Climbing (Known bug #209)
  // =========================================================================
  test.describe('3 - Spire / Climbing', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('KNOWN BUG #209: Climb the Spire should not crash with React error #185', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      // Look for "Climb the Spire" button or Spire tab
      const spireTab = page.getByRole('tab', { name: /spire/i });
      const climbButton = page.getByRole('button', { name: /climb/i });

      if (await spireTab.isVisible({ timeout: 5000 })) {
        await spireTab.click();
        await waitForTicks(page, 300);
      }

      if (await climbButton.isVisible({ timeout: 5000 })) {
        await climbButton.click();
        await waitForTicks(page, 2000);

        const reactErrors = errors.filter(e =>
          e.includes('Maximum update depth') || e.includes('Error #185')
        );
        // This is a known bug - we expect it to fail
        if (reactErrors.length > 0) {
          console.log('KNOWN BUG #209 CONFIRMED: Spire crash detected');
        } else {
          console.log('KNOWN BUG #209: No crash detected - may be fixed');
        }
      } else {
        console.log('Climb the Spire button not found - may need setup');
      }
    });
  });

  // =========================================================================
  // SECTION 4 - Disciplines Tab
  // =========================================================================
  test.describe('4 - Disciplines', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Disciplines tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const discTab = page.getByRole('tab', { name: /disciplines/i });
      if (await discTab.isVisible({ timeout: 5000 })) {
        await discTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Disciplines: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });

    test('Raw Mana Mastery discipline is available', async ({ page }) => {
      await waitForTicks(page, 500);
      const discTab = page.getByRole('tab', { name: /disciplines/i });
      if (await discTab.isVisible({ timeout: 5000 })) {
        await discTab.click();
        await waitForTicks(page, 300);
        const bodyText = await page.textContent('body') || '';
        // Raw Mana Mastery should be available since Enchanter is attuned
        if (bodyText.includes('Raw Mana Mastery')) {
          console.log('DISCIPLINE: Raw Mana Mastery found');
        }
      }
    });
  });

  // =========================================================================
  // SECTION 5 - Crafting Tab
  // =========================================================================
  test.describe('5 - Crafting System', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Crafting tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const craftTab = page.getByRole('tab', { name: /craft/i });
      if (await craftTab.isVisible({ timeout: 5000 })) {
        await craftTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Crafting: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });

    test('Enchant sub-tab exists and is clickable', async ({ page }) => {
      await waitForTicks(page, 500);
      const craftTab = page.getByRole('tab', { name: /craft/i });
      if (await craftTab.isVisible({ timeout: 5000 })) {
        await craftTab.click();
        await waitForTicks(page, 300);
        // Look for Enchant sub-tab or section
        const bodyText = await page.textContent('body') || '';
        expect(bodyText).toBeTruthy();
      }
    });
  });

  // =========================================================================
  // SECTION 6 - Equipment Tab
  // =========================================================================
  test.describe('6 - Equipment & Inventory', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Equipment tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const equipTab = page.getByRole('tab', { name: /equipment/i });
      if (await equipTab.isVisible({ timeout: 5000 })) {
        await equipTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Equipment: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });

    test('starting equipment includes Basic Staff, Civilian Shirt, Civilian Shoes', async ({ page }) => {
      await waitForTicks(page, 500);
      const equipTab = page.getByRole('tab', { name: /equipment/i });
      if (await equipTab.isVisible({ timeout: 5000 })) {
        await equipTab.click();
        await waitForTicks(page, 300);
        const bodyText = await page.textContent('body') || '';
        // Check for starting equipment
        console.log('EQUIPMENT: Checking starting equipment...');
        if (bodyText.includes('Basic Staff')) {
          console.log('EQUIPMENT: Basic Staff found ✓');
        }
        if (bodyText.includes('Civilian Shirt')) {
          console.log('EQUIPMENT: Civilian Shirt found ✓');
        }
        if (bodyText.includes('Civilian Shoes') || bodyText.includes('Civilian')) {
          console.log('EQUIPMENT: Civilian gear found ✓');
        }
      }
    });
  });

  // =========================================================================
  // SECTION 7 - Attunements Tab
  // =========================================================================
  test.describe('7 - Attunements', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Attunements tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const attuneTab = page.getByRole('tab', { name: /attun/i });
      if (await attuneTab.isVisible({ timeout: 5000 })) {
        await attuneTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Attunements: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });

    test('Enchanter is attuned at level 1 by default', async ({ page }) => {
      await waitForTicks(page, 500);
      const attuneTab = page.getByRole('tab', { name: /attun/i });
      if (await attuneTab.isVisible({ timeout: 5000 })) {
        await attuneTab.click();
        await waitForTicks(page, 300);
        const bodyText = await page.textContent('body') || '';
        if (bodyText.includes('Enchanter')) {
          console.log('ATTUNEMENT: Enchanter found ✓');
        }
      }
    });
  });

  // =========================================================================
  // SECTION 8 - Spells Tab
  // =========================================================================
  test.describe('8 - Spells Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Spells tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const spellsTab = page.getByRole('tab', { name: /spell/i });
      if (await spellsTab.isVisible({ timeout: 5000 })) {
        await spellsTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Spells: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 9 - Prestige Tab
  // =========================================================================
  test.describe('9 - Prestige Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Prestige tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const prestigeTab = page.getByRole('tab', { name: /prestige/i });
      if (await prestigeTab.isVisible({ timeout: 5000 })) {
        await prestigeTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Prestige: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 10 - Golemancy Tab
  // =========================================================================
  test.describe('10 - Golemancy Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Golemancy tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const golemTab = page.getByRole('tab', { name: /golem/i });
      if (await golemTab.isVisible({ timeout: 5000 })) {
        await golemTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Golemancy: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 11 - Guardian Pacts Tab
  // =========================================================================
  test.describe('11 - Guardian Pacts Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Guardian Pacts tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const pactsTab = page.getByRole('tab', { name: /pact/i });
      if (await pactsTab.isVisible({ timeout: 5000 })) {
        await pactsTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Guardian Pacts: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 12 - Grimoire Tab
  // =========================================================================
  test.describe('12 - Grimoire Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Grimoire tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const grimoireTab = page.getByRole('tab', { name: /grimoire/i });
      if (await grimoireTab.isVisible({ timeout: 5000 })) {
        await grimoireTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Grimoire: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 13 - Achievements Tab
  // =========================================================================
  test.describe('13 - Achievements Tab', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Achievements tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const achTab = page.getByRole('tab', { name: /achievement/i });
      if (await achTab.isVisible({ timeout: 5000 })) {
        await achTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Achievements: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 14 - Debug Tab & Cheats
  // =========================================================================
  test.describe('14 - Debug Tab & Cheats', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('navigate to Debug tab without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const debugTab = page.getByRole('tab', { name: /debug/i });
      if (await debugTab.isVisible({ timeout: 5000 })) {
        await debugTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Debug: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });
  });

  // =========================================================================
  // SECTION 15 - Deep Bug Hunting with Debug Console
  // =========================================================================
  test.describe('15 - Deep Bug Hunting (Debug Mode)', () => {
    test.beforeEach(async ({ page }) => {
      await startFreshGame(page);
    });

    test('mana regen values in ManaDisplay are correct', async ({ page }) => {
      await waitForTicks(page, 1000);
      const bodyText = await page.textContent('body') || '';
      // Check that mana regen shows positive values for Transference
      // Look for regen rate patterns like "+X/hr"
      console.log('HUNT: Checking mana regen display values');
      const matches = bodyText.match(/\+[\d.]+(\/hr)?/g);
      console.log(`HUNT: Found regen patterns: ${JSON.stringify(matches)}`);
    });

    test('element tab shows correct element unlock status', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      // Try to find element-related tabs
      const elemTab = page.getByRole('tab', { name: /element/i });
      if (await elemTab.isVisible({ timeout: 3000 })) {
        await elemTab.click();
        await waitForTicks(page, 500);
        const reactErrors = errors.filter(e =>
          e.includes('React') || e.includes('Minified') || e.includes('Error #')
        );
        expect(reactErrors, `React errors in Elements: ${JSON.stringify(reactErrors)}`).toHaveLength(0);
      }
    });

    test('mana values stay consistent after multiple ticks', async ({ page }) => {
      await waitForTicks(page, 500);
      // Take a snapshot of mana values
      const bodyBefore = await page.textContent('body') || '';
      await waitForTicks(page, 2000);
      const bodyAfter = await page.textContent('body') || '';
      // Game should still be running (no crash)
      expect(bodyAfter).toBeTruthy();
      console.log('HUNT: Game still running after 2 seconds of ticking ✓');
    });

    test('all navigations work in sequence without crash', async ({ page }) => {
      const errors: string[] = [];
      page.on('console', (msg) => {
        if (msg.type() === 'error') errors.push(msg.text());
      });
      await waitForTicks(page, 500);

      const tabs = [
        'stats', 'equipment', 'attunements', 'crafting', 'disciplines',
        'spells', 'prestige', 'golemancy', 'pacts', 'achievements',
        'grimoire', 'debug'
      ];

      const visitedTabs: string[] = [];
      const crashTabs: string[] = [];

      for (const tabName of tabs) {
        const tab = page.getByRole('tab', { name: new RegExp(tabName, 'i') });
        if (await tab.isVisible({ timeout: 2000 })) {
          const preErrors = [...errors];
          await tab.click();
          await waitForTicks(page, 300);
          const newErrors = errors.filter(e => !preErrors.includes(e));
          const reactErrors = newErrors.filter(e =>
            e.includes('React') || e.includes('Minified') || e.includes('Error #')
          );
          if (reactErrors.length > 0) {
            crashTabs.push(tabName);
          }
          visitedTabs.push(tabName);
        }
      }

      console.log(`HUNT: Visited tabs: ${visitedTabs.join(', ')}`);
      console.log(`HUNT: Tabs with React errors: ${crashTabs.join(', ')}`);
    });
  });
});
