/**
 * commands/vitest-doctor.mjs — FRAMEWORK-BUG-026 diagnostic subcommand.
 *
 * Globs every `vitest.config.{ts,js,mjs}` under the project root (skipping
 * node_modules), parses each for the two shim signals the framework
 * centralizes in `packages/framework/test-utils/vitest.shared.mjs`:
 *
 *   - `NODE_ENV='test'`            (process.env.NODE_ENV set OR defineVitestShim active)
 *   - `oxc.jsx.runtime='automatic'` (jsxAutomaticShim active)
 *
 * Reports a matrix and warns when a workspace has JSX-rendering tests
 * (any `*.test.tsx` under `src/`) but no jsxAutomaticShim coverage —
 * that's the BUG-026 first-test paper cut.
 *
 * Exit codes:
 *   0 — no warnings (or only informational matrix output)
 *   1 — at least one workspace has JSX-rendering tests without
 *       jsxAutomaticShim coverage
 */
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
import { join, relative, resolve } from 'node:path';
import { parseFlags } from '../util/args.mjs';
import { err, exitWith, ok } from '../util/result.mjs';
const VITEST_CONFIG_NAMES = new Set(['vitest.config.ts', 'vitest.config.js', 'vitest.config.mjs']);
const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'out', '.next', '.aperant']);
export function cmdVitestDoctor(projectDir, extraArgs) {
    if (!projectDir)
        return err('Usage: apt-tools vitest doctor <project-dir> [--format json|md]');
    const root = resolve(projectDir);
    if (!existsSync(root))
        return err(`project-dir not found: ${root}`);
    const flags = parseFlags(extraArgs ?? []);
    const format = (flags.get('format') || 'json').toLowerCase();
    const configs = findVitestConfigs(root);
    const matrix = configs.map((configPath) => inspectConfig(root, configPath));
    const warnings = matrix
        .filter((row) => row.has_jsx_rendering_tests && !row.jsx_automatic_shim)
        .map((row) => ({
        workspace: row.workspace,
        reason: 'has JSX-rendering tests under src/ but vitest.config does not enable jsxAutomaticShim',
    }));
    const envelope = {
        status: 'ok',
        command: 'vitest-doctor',
        project_dir: root,
        configs_found: matrix.length,
        matrix,
        warnings,
    };
    if (format === 'md') {
        envelope.markdown = renderMarkdown(matrix, warnings);
    }
    if (warnings.length > 0) {
        // Exit code 1 — surface drift so the user knows to wire the shim.
        return exitWith(envelope, 1);
    }
    return ok(envelope);
}
function findVitestConfigs(root) {
    const out = [];
    walk(root, root, out);
    return out;
}
function walk(rootAbs, dirAbs, out) {
    let names;
    try {
        names = readdirSync(dirAbs);
    }
    catch {
        return;
    }
    for (const name of names) {
        if (SKIP_DIRS.has(name))
            continue;
        const abs = join(dirAbs, name);
        let st;
        try {
            st = statSync(abs);
        }
        catch {
            continue;
        }
        if (st.isDirectory()) {
            walk(rootAbs, abs, out);
        }
        else if (st.isFile() && VITEST_CONFIG_NAMES.has(name)) {
            out.push(abs);
        }
    }
}
function inspectConfig(rootAbs, configPath) {
    const workspace = relative(rootAbs, configPath);
    const dir = join(configPath, '..');
    let body = '';
    try {
        body = readFileSync(configPath, 'utf-8');
    }
    catch {
        return {
            workspace,
            node_env_shim: false,
            jsx_automatic_shim: false,
            has_jsx_rendering_tests: false,
            error: 'read-failed',
        };
    }
    // NODE_ENV shim: either the literal `process.env.NODE_ENV = 'test'`
    // pattern OR `defineVitestShim(` (any non-explicit-false arg).
    const node_env_shim = /process\.env\.NODE_ENV\s*=\s*['"`]test['"`]/.test(body) ||
        /defineVitestShim\([^)]*\)/.test(body);
    // jsxAutomaticShim: literal `oxc.jsx.runtime` = 'automatic' OR
    // `jsxAutomaticShim: true` inside a defineVitestShim() arg.
    const jsx_automatic_shim = /oxc\s*:\s*\{[^}]*jsx[^}]*runtime\s*:\s*['"`]automatic['"`]/s.test(body) ||
        /jsxAutomaticShim\s*:\s*true/.test(body);
    const has_jsx_rendering_tests = workspaceHasJsxRenderingTests(dir);
    return { workspace, node_env_shim, jsx_automatic_shim, has_jsx_rendering_tests };
}
function workspaceHasJsxRenderingTests(workspaceDir) {
    const srcDir = join(workspaceDir, 'src');
    if (!existsSync(srcDir))
        return false;
    return scanForTsxTest(srcDir);
}
function scanForTsxTest(dirAbs) {
    let names;
    try {
        names = readdirSync(dirAbs);
    }
    catch {
        return false;
    }
    for (const name of names) {
        if (SKIP_DIRS.has(name))
            continue;
        const abs = join(dirAbs, name);
        let st;
        try {
            st = statSync(abs);
        }
        catch {
            continue;
        }
        if (st.isDirectory()) {
            if (scanForTsxTest(abs))
                return true;
        }
        else if (st.isFile() && /\.test\.tsx$/.test(name)) {
            return true;
        }
    }
    return false;
}
function renderMarkdown(matrix, warnings) {
    const lines = ['## vitest-doctor matrix', ''];
    lines.push('| workspace | NODE_ENV shim | jsxAutomaticShim | has JSX tests |');
    lines.push('|-----------|---------------|------------------|---------------|');
    for (const r of matrix) {
        lines.push(`| \`${r.workspace}\` | ${r.node_env_shim ? '✓' : '✗'} | ${r.jsx_automatic_shim ? '✓' : '✗'} | ${r.has_jsx_rendering_tests ? '✓' : '—'} |`);
    }
    if (warnings.length > 0) {
        lines.push('', '## Warnings', '');
        for (const w of warnings) {
            lines.push(`- \`${w.workspace}\` — ${w.reason}`);
        }
    }
    return lines.join('\n');
}
//# sourceMappingURL=vitest-doctor.mjs.map