#!/usr/bin/env node
/**
 * Audit: extract all HS sources from behavioral tests and check parse/compile.
 * Uses child_process.execSync with timeout to handle hangs.
 */
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const PROJECT = path.resolve(__dirname, '..');

// Extract HS sources from test file with their suite/test names
const testSx = fs.readFileSync(path.join(PROJECT, 'spec/tests/test-hyperscript-behavioral.sx'), 'utf8');

// Extract suites and their test counts from comments
const suitePattern = /;; ── (\S+) \((\d+) tests\)/g;
const suites = [];
let m;
while ((m = suitePattern.exec(testSx)) !== null) {
  suites.push({ name: m[1], count: parseInt(m[2]) });
}

console.log('Test suites (831 total):');
let grandTotal = 0;
for (const s of suites) {
  grandTotal += s.count;
  console.log(`  ${s.name}: ${s.count}`);
}
console.log(`  TOTAL: ${grandTotal}`);

// Categorize tests by type: DOM-action tests vs eval-only tests vs stub tests
const lines = testSx.split('\n');
let currentSuite = '';
let inDeftest = false;
let testName = '';
let testBody = '';
let depth = 0;

const testCategories = {};

for (const line of lines) {
  const suiteMatch = line.match(/\(defsuite\s+"([^"]+)"/);
  if (suiteMatch) { currentSuite = suiteMatch[1]; continue; }

  const testMatch = line.match(/\(deftest\s+"([^"]+)"/);
  if (testMatch) { inDeftest = true; testName = testMatch[1]; testBody = line; depth = 1; continue; }

  if (inDeftest) {
    testBody += '\n' + line;
    depth += (line.match(/\(/g) || []).length - (line.match(/\)/g) || []).length;
    if (depth <= 0) {
      // Categorize this test
      if (!testCategories[currentSuite]) testCategories[currentSuite] = { domAction: 0, evalOnly: 0, stub: 0, notImpl: 0, names: [] };

      if (testBody.includes('NOT IMPLEMENTED') || testBody.includes('not-implemented')) {
        testCategories[currentSuite].stub++;
      } else if (testBody.includes('dom-dispatch') || testBody.includes('dom-set-inner-html') && testBody.includes('hs-activate!')) {
        testCategories[currentSuite].domAction++;
        testCategories[currentSuite].names.push(testName);
      } else if (testBody.includes('eval-hs') || testBody.includes('hs-eval')) {
        testCategories[currentSuite].evalOnly++;
      } else {
        testCategories[currentSuite].domAction++;
        testCategories[currentSuite].names.push(testName);
      }

      inDeftest = false;
      testBody = '';
    }
  }
}

// Count unique HS sources
const attrPattern = /dom-set-attr\s+\S+\s+"_"\s+"([^"]+)"/g;
const hsSources = new Set();
while ((m = attrPattern.exec(testSx)) !== null) {
  hsSources.add(m[1].replace(/\\"/g, '"'));
}

console.log(`\n${hsSources.size} unique HS sources across ${grandTotal} tests`);

// Analyze HS source complexity
const features = {
  'on click': 0, 'on load': 0, 'on keyup': 0, 'on mouseenter': 0,
  'on mutation': 0, 'on intersect': 0, 'on every': 0,
  'add .': 0, 'remove .': 0, 'toggle .': 0, 'set ': 0, 'put ': 0,
  'if ': 0, 'repeat': 0, 'wait ': 0, 'send ': 0, 'take ': 0,
  'transition': 0, 'hide': 0, 'show': 0, 'log': 0,
  'call ': 0, 'fetch ': 0, 'tell ': 0, 'halt': 0,
  'morph': 0, 'go ': 0, 'append': 0, 'settle': 0,
  'def ': 0, 'increment': 0, 'decrement': 0,
  'bind ': 0, 'closest': 0, 'in ': 0, 'as ': 0,
  'init': 0, 'every ': 0, 'measure': 0,
};

for (const src of hsSources) {
  for (const feat of Object.keys(features)) {
    if (src.includes(feat)) features[feat]++;
  }
}

console.log('\nFeature usage in test sources:');
for (const [feat, count] of Object.entries(features).sort((a,b) => b[1] - a[1])) {
  if (count > 0) console.log(`  ${feat.trim()}: ${count}`);
}

// Summarize categories
console.log('\nPer-suite breakdown:');
let totalDom = 0, totalEval = 0, totalStub = 0;
for (const [suite, cat] of Object.entries(testCategories).sort((a,b) => (b[1].domAction+b[1].evalOnly) - (a[1].domAction+a[1].evalOnly))) {
  const total = cat.domAction + cat.evalOnly + cat.stub;
  totalDom += cat.domAction;
  totalEval += cat.evalOnly;
  totalStub += cat.stub;
  console.log(`  ${suite}: ${total} tests (${cat.domAction} DOM, ${cat.evalOnly} eval, ${cat.stub} stub)`);
}
console.log(`\nTotals: ${totalDom} DOM-action, ${totalEval} eval-only, ${totalStub} stubs`);
