#!/usr/bin/env node
/**
 * run-sx-tests.js — Run SX deftest forms in the Node WASM harness.
 *
 * Loads island definitions + test file, runs all registered tests,
 * reports results.
 *
 * Usage:
 *   node tests/node/run-sx-tests.js [test-file.sx]
 */
const { createSxEnv } = require('./sx-harness');
const fs = require('fs');
const path = require('path');

const DEFAULT_TEST_FILE = path.resolve(__dirname, '../../spec/tests/test-reactive-islands.sx');
const ISLAND_SRC = path.resolve(__dirname, '../../sx/sx/reactive-islands/index.sx');

async function main() {
  const testFile = process.argv[2] || DEFAULT_TEST_FILE;
  const origLog = console.log;
  const origErr = console.error;

  origLog(`=== SX Test Runner (Node+WASM) ===`);
  origLog(`Test file: ${path.basename(testFile)}\n`);

  const t0 = Date.now();

  const env = await createSxEnv({
    html: '<div id="portal-root"></div>',
  });

  // Load island definitions
  const islandSrc = fs.readFileSync(ISLAND_SRC, 'utf8');
  env.load(islandSrc);

  // Load test file
  const testSrc = fs.readFileSync(testFile, 'utf8');
  env.load(testSrc);

  // Get registered tests
  const tests = env.eval('_island-tests');
  const testList = tests?.items || [];

  if (testList.length === 0) {
    origLog('No tests found (check _island-tests registry)');
    env.close();
    process.exit(1);
  }

  origLog(`Running ${testList.length} tests...\n`);

  let passed = 0, failed = 0;
  const failures = [];

  for (const test of testList) {
    const name = test.name;
    const fn = test.fn;
    try {
      env.K.callFn(fn, []);
      passed++;
      origLog(`  \u2713 ${name}`);
    } catch (e) {
      failed++;
      const msg = e.message || String(e);
      // Extract the assertion message from the error
      const clean = msg.replace(/^Error:\s*/, '').replace(/\s*\(in .*$/, '');
      origErr(`  \u2717 ${name}: ${clean}`);
      failures.push({ name, error: clean });
    }
  }

  env.close();

  const dt = Date.now() - t0;
  origLog(`\n=== ${passed} passed, ${failed} failed (${dt}ms) ===`);
  if (failures.length > 0) {
    origLog('\nFailures:');
    for (const f of failures) origLog(`  ${f.name}: ${f.error}`);
  }
  process.exit(failed > 0 ? 1 : 0);
}

main().catch(e => { console.error(e); process.exit(1); });
