#!/usr/bin/env node

const { execFileSync } = require('child_process');
const { globSync } = require('glob');
const path = require('path');
const fs = require('fs');

const args = process.argv.slice(2);
const nodeArgs = ['--import', 'tsx'];
const patterns = [];
const excludePatterns = [];
let perFile = false;
const nodeMajor = Number.parseInt(process.versions.node.split('.')[0], 10);
const nativeTestArgs = nodeMajor >= 22 ? ['--test-force-exit'] : [];

// Derive a unique package name for JUnit XML output
function getPackageName() {
  try {
    const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
    return (pkg.name || 'unknown').replace(/[^a-zA-Z0-9-]/g, '_');
  } catch {
    return 'unknown';
  }
}

let i = 0;
while (i < args.length) {
  const arg = args[i];
  if (arg === '--') {
    i += 1;
    break;
  }
  if (arg === '--per-file') {
    perFile = true;
    i += 1;
    continue;
  }
  if (arg === '--exclude') {
    const value = args[i + 1];
    if (!value) {
      console.error('Missing value for --exclude');
      process.exit(1);
    }
    excludePatterns.push(value);
    i += 2;
    continue;
  }
  if (arg === '--import') {
    const value = args[i + 1];
    if (!value) {
      console.error('Missing value for --import');
      process.exit(1);
    }
    nodeArgs.push(arg, value);
    i += 2;
    continue;
  }
  nodeArgs.push(arg);
  i += 1;
}

patterns.push(...args.slice(i));

if (patterns.length === 0) {
  console.error('No test patterns provided');
  process.exit(1);
}

const files = [...new Set(patterns.flatMap((pattern) => globSync(pattern)).sort())];
const excluded = new Set(excludePatterns.flatMap((pattern) => globSync(pattern)));
const filteredFiles = files.filter((file) => !excluded.has(file));
if (filteredFiles.length === 0) {
  console.error('No test files found for patterns:', patterns.join(', '));
  process.exit(1);
}

// When CI_JUNIT_DIR is set, add dual reporter: spec to stdout + junit to file
const junitArgs = [];
if (process.env.CI_JUNIT_DIR) {
  const junitDir = process.env.CI_JUNIT_DIR;
  const pkgName = getPackageName();
  const junitFile = path.join(junitDir, `${pkgName}.xml`);
  fs.mkdirSync(junitDir, { recursive: true });
  junitArgs.push(
    '--test-reporter=spec', '--test-reporter-destination=stdout',
    '--test-reporter=junit', `--test-reporter-destination=${junitFile}`
  );
}

const testRunnerArgs = junitArgs.length > 0 ? junitArgs : [];

if (perFile) {
  for (const file of filteredFiles) {
    execFileSync(process.execPath, [...nodeArgs, ...testRunnerArgs, ...nativeTestArgs, '--test', file], {
      cwd: process.cwd(),
      stdio: 'inherit',
    });
  }
} else {
  execFileSync(process.execPath, [...nodeArgs, ...testRunnerArgs, ...nativeTestArgs, '--test', ...filteredFiles], {
    cwd: process.cwd(),
    stdio: 'inherit',
  });
}
