/**
 * Vigthoria CLI — Post-Write Validator / Self-Healing Layer
 *
 * After the V3 agent writes files to the workspace, this module:
 *   1. Detects available validators (tsc, npm test, py_compile).
 *   2. Runs them in the project directory.
 *   3. Returns structured pass/fail results for each tool.
 *
 * Used by runSelfHealingCycle in api.ts to send targeted correction prompts.
 */
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
function commandExists(cmd, args = ['--version']) {
    try {
        execFileSync(cmd, args, { stdio: 'pipe', timeout: 4000, windowsHide: true });
        return true;
    }
    catch {
        return false;
    }
}
function hasTsConfig(dir) {
    return fs.existsSync(path.join(dir, 'tsconfig.json'));
}
/**
 * Resolve the best available tsc binary for the project.
 * Prefers local node_modules/.bin/tsc over npx to avoid network fetches.
 */
function resolveTscBin(workspacePath) {
    const localTsc = path.join(workspacePath, 'node_modules', '.bin', 'tsc');
    if (fs.existsSync(localTsc))
        return { cmd: localTsc, args: ["--noEmit", "--skipLibCheck"] };
    try {
        execFileSync("tsc", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
        return { cmd: "tsc", args: ["--noEmit", "--skipLibCheck"] };
    }
    catch { /* tsc not available */ }
    try {
        execFileSync("npx", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
        return { cmd: "npx", args: ["--yes", "tsc", "--noEmit", "--skipLibCheck"] };
    }
    catch { /* npx not available */ }
    return null;
}
function hasRealTestScript(dir) {
    try {
        const pkgPath = path.join(dir, 'package.json');
        if (!fs.existsSync(pkgPath))
            return false;
        const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
        const script = pkg.scripts?.test ?? '';
        return typeof script === 'string' && script.length > 0
            && !script.startsWith('echo "Error: no test specified"');
    }
    catch {
        return false;
    }
}
/**
 * Run post-write validation in the project directory.
 * Each check is time-bounded to avoid blocking the CLI.
 */
export async function runPostWriteValidation(workspacePath) {
    if (!workspacePath || !fs.existsSync(workspacePath))
        return [];
    const results = [];
    const opts = { cwd: workspacePath, stdio: 'pipe', windowsHide: true };
    // 1. TypeScript type check
    const tscBin = hasTsConfig(workspacePath) ? resolveTscBin(workspacePath) : null;
    if (tscBin) {
        try {
            execFileSync(tscBin.cmd, tscBin.args, { ...opts, timeout: 45_000 });
            results.push({ ran: true, tool: 'tsc', passed: true, output: '' });
        }
        catch (err) {
            const out = [err.stderr?.toString(), err.stdout?.toString()].filter(Boolean).join('\n').slice(0, 4000);
            results.push({ ran: true, tool: 'tsc', passed: false, output: out });
        }
    }
    // 2. npm test
    if (hasRealTestScript(workspacePath) && commandExists('npm')) {
        try {
            execFileSync('npm', ['test', '--', '--passWithNoTests'], { ...opts, timeout: 90_000 });
            results.push({ ran: true, tool: 'npm test', passed: true, output: '' });
        }
        catch (err) {
            const out = [err.stderr?.toString(), err.stdout?.toString()].filter(Boolean).join('\n').slice(0, 4000);
            results.push({ ran: true, tool: 'npm test', passed: false, output: out });
        }
    }
    // 3. Python syntax check
    const hasPy = fs.existsSync(path.join(workspacePath, 'requirements.txt'))
        || fs.existsSync(path.join(workspacePath, 'setup.py'))
        || fs.existsSync(path.join(workspacePath, 'pyproject.toml'));
    if (hasPy && commandExists('python3', ['-c', 'import ast'])) {
        const pyFiles = [];
        try {
            const entries = fs.readdirSync(workspacePath, { withFileTypes: true });
            for (const e of entries) {
                if (e.isFile() && e.name.endsWith('.py'))
                    pyFiles.push(e.name);
            }
        }
        catch { /* ignore */ }
        let pyPassed = true;
        let pyOut = '';
        for (const pyFile of pyFiles.slice(0, 20)) {
            try {
                execFileSync('python3', ['-m', 'py_compile', pyFile], { ...opts, timeout: 10_000 });
            }
            catch (err) {
                pyPassed = false;
                pyOut += `${pyFile}: ${err.stderr?.toString()?.trim() || 'syntax error'}\n`;
            }
        }
        if (pyFiles.length > 0) {
            results.push({ ran: true, tool: 'py_compile', passed: pyPassed, output: pyOut.slice(0, 2000) });
        }
    }
    return results;
}
/**
 * Build a clear error summary string from failed validation results.
 */
export function formatValidationErrors(results) {
    return results
        .filter((r) => r.ran && !r.passed)
        .map((r) => `[${r.tool}]\n${r.output.trim()}`)
        .join('\n\n─────────────────────────\n\n');
}
