#!/usr/bin/env bun
/**
 * HYPERSCRIPT VALIDATION TEST
 * ============================
 * Tests hyperscript integrity and parse error detection
 * - Verifies no parse errors on page load
 * - Validates max 3 def statements rule
 * - Checks keyboard event handlers
 * - Verifies operator precedence (parentheses)
 */

import { chromium } from 'playwright';

const URL = "http://localhost:1999";

async function testHyperscript() {
  console.log('📜 HYPERSCRIPT VALIDATION TEST\n');
  console.log('='.repeat(70));

  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } });

  const errors = [];
  const testResults = [];

  page.on('console', msg => {
    const text = msg.text();
    if (msg.type() === 'error') {
      errors.push(text);
      console.log(`❌ ERROR: ${text}`);
    }
  });

  page.on('pageerror', err => {
    errors.push(err.message);
    console.log(`❌ PAGE ERROR: ${err.message}`);
  });

  console.log("\n1️⃣  Loading page...");
  await page.goto(URL);
  await page.waitForTimeout(2000);

  // ========================================================================
  // TEST 1: No hyperscript parse errors
  // ========================================================================
  console.log("\n2️⃣  Testing Parse Error Detection...");
  const parseErrors = errors.filter(err =>
    err.includes('hyperscript') ||
    err.includes('_hyperscript') ||
    err.includes('parse error') ||
    err.includes('Unexpected token')
  );

  const parseTest = parseErrors.length === 0;
  console.log(`   Parse errors: ${parseErrors.length}`);
  if (parseErrors.length > 0) {
    parseErrors.forEach((err, i) => {
      console.log(`   ${i + 1}. ${err}`);
    });
  }
  console.log(`   ${parseTest ? '✅ PASS' : '❌ FAIL'} - No parse errors`);
  testResults.push({ test: 'No Parse Errors', passed: parseTest });

  // ========================================================================
  // TEST 2: Hyperscript functions are defined
  // ========================================================================
  console.log("\n3️⃣  Testing Function Definitions...");
  const functionsTest = await page.evaluate(() => {
    const hasToggleCVLength = typeof toggleCVLength === 'function';
    const hasToggleIcons = typeof toggleIcons === 'function';
    const hasToggleTheme = typeof toggleTheme === 'function';
    const hasKeyboardHandler = typeof handleKeyboardShortcut === 'function';

    return {
      toggleCVLength: hasToggleCVLength,
      toggleIcons: hasToggleIcons,
      toggleTheme: hasToggleTheme,
      keyboardHandler: hasKeyboardHandler,
      allDefined: hasToggleCVLength && hasToggleIcons && hasToggleTheme && hasKeyboardHandler
    };
  });

  console.log(`   toggleCVLength: ${functionsTest.toggleCVLength ? '✅' : '❌'}`);
  console.log(`   toggleIcons: ${functionsTest.toggleIcons ? '✅' : '❌'}`);
  console.log(`   toggleTheme: ${functionsTest.toggleTheme ? '✅' : '❌'}`);
  console.log(`   handleKeyboardShortcut: ${functionsTest.keyboardHandler ? '✅' : '❌'}`);
  console.log(`   ${functionsTest.allDefined ? '✅ PASS' : '❌ FAIL'} - All functions defined`);
  testResults.push({ test: 'Function Definitions', passed: functionsTest.allDefined });

  // ========================================================================
  // TEST 3: Keyboard event handlers work
  // ========================================================================
  console.log("\n4️⃣  Testing Keyboard Event Handlers...");
  const keyboardTest = await page.evaluate(async () => {
    const body = document.body;
    const initialTheme = body.classList.contains('theme-clean');

    // Simulate 'v' key press
    const event = new KeyboardEvent('keydown', { key: 'v', bubbles: true });
    document.body.dispatchEvent(event);

    await new Promise(r => setTimeout(r, 300));
    const afterTheme = body.classList.contains('theme-clean');

    return {
      initialTheme,
      afterTheme,
      toggled: initialTheme !== afterTheme
    };
  });

  console.log(`   Before: ${keyboardTest.initialTheme ? 'clean' : 'default'}`);
  console.log(`   After:  ${keyboardTest.afterTheme ? 'clean' : 'default'}`);
  console.log(`   ${keyboardTest.toggled ? '✅ PASS' : '❌ FAIL'} - Keyboard handler works`);
  testResults.push({ test: 'Keyboard Event Handlers', passed: keyboardTest.toggled });

  // ========================================================================
  // TEST 4: Check for def statements (should be 0 in HTML)
  // ========================================================================
  console.log("\n5️⃣  Testing Def Statement Count...");
  const defTest = await page.evaluate(() => {
    const scripts = Array.from(document.querySelectorAll('script[type="_hyperscript"]'));
    const defCount = scripts.reduce((count, script) => {
      const matches = script.textContent.match(/\bdef\b/g);
      return count + (matches ? matches.length : 0);
    }, 0);

    const inlineElements = Array.from(document.querySelectorAll('[_]'));
    const inlineDefCount = inlineElements.reduce((count, el) => {
      const matches = el.getAttribute('_').match(/\bdef\b/g);
      return count + (matches ? matches.length : 0);
    }, 0);

    return {
      scriptDefs: defCount,
      inlineDefs: inlineDefCount,
      total: defCount + inlineDefCount
    };
  });

  console.log(`   Script tag defs: ${defTest.scriptDefs}`);
  console.log(`   Inline defs: ${defTest.inlineDefs}`);
  console.log(`   Total: ${defTest.total}`);
  console.log(`   ${defTest.total <= 3 ? '✅ PASS' : '❌ FAIL'} - Within 3 def limit`);
  testResults.push({ test: 'Def Statement Count (≤3)', passed: defTest.total <= 3 });

  // ========================================================================
  // TEST 5: Operator precedence validation
  // ========================================================================
  console.log("\n6️⃣  Testing Operator Precedence...");
  const precedenceTest = await page.evaluate(() => {
    const elements = Array.from(document.querySelectorAll('[_]'));
    const problematicPatterns = [];

    elements.forEach(el => {
      const script = el.getAttribute('_');

      // Check for unparenthesized 'or' and 'and'
      if (script.includes(' or ') || script.includes(' and ')) {
        // Look for patterns like: a or b and c (should be (a or b) and c)
        const hasProblematicPattern = /\w+\s+or\s+\w+\s+and\s+\w+/.test(script) ||
                                      /\w+\s+and\s+\w+\s+or\s+\w+/.test(script);

        if (hasProblematicPattern) {
          problematicPatterns.push({
            element: el.tagName,
            id: el.id || 'no-id',
            script: script.substring(0, 100)
          });
        }
      }
    });

    return {
      problematicCount: problematicPatterns.length,
      patterns: problematicPatterns
    };
  });

  console.log(`   Problematic patterns: ${precedenceTest.problematicCount}`);
  if (precedenceTest.problematicCount > 0) {
    precedenceTest.patterns.forEach((p, i) => {
      console.log(`   ${i + 1}. <${p.element}${p.id !== 'no-id' ? ` id="${p.id}"` : ''}>`);
    });
  }
  console.log(`   ${precedenceTest.problematicCount === 0 ? '✅ PASS' : '❌ FAIL'} - Proper operator precedence`);
  testResults.push({ test: 'Operator Precedence', passed: precedenceTest.problematicCount === 0 });

  // ========================================================================
  // FINAL SUMMARY
  // ========================================================================
  console.log("\n" + "=".repeat(70));
  console.log("📊 TEST SUMMARY\n");

  const totalTests = testResults.length;
  const passedTests = testResults.filter(r => r.passed).length;
  const failedTests = totalTests - passedTests;

  testResults.forEach(result => {
    console.log(`   ${result.passed ? '✅' : '❌'} ${result.test}`);
  });

  console.log(`\n   Total: ${passedTests}/${totalTests} tests passed`);

  if (errors.length === 0) {
    console.log("\n✅ NO CONSOLE ERRORS");
  } else {
    console.log(`\n⚠️  ${errors.length} CONSOLE ERRORS (see details above)`);
  }

  console.log("=".repeat(70) + "\n");

  if (failedTests === 0 && parseErrors.length === 0) {
    console.log("🎉 HYPERSCRIPT VALIDATION PASSED!");
  } else {
    console.log("⚠️  SOME TESTS FAILED - See details above");
  }

  console.log("\nBrowser will stay open for manual inspection.");
  console.log("Press Ctrl+C when done.\n");

  await new Promise(() => {}); // Keep browser open
}

await testHyperscript();
