/**
 * install/archetype.mjs — greenfield vs brownfield detection.
 *
 * Runs once during `apt-tools init` to pick sensible defaults + drive
 * conditional prompts (e.g. "scan existing code now?" only makes sense
 * on brownfield). Cheap, single-pass — no filesystem recursion.
 *
 * Signals we look for (positive = brownfield):
 *   - `src/` directory exists
 *   - `tests/` or `__tests__/` directory exists
 *   - `package.json` exists AND has ≥1 dependency/devDependency
 *   - `git` directory exists AND has ≥10 commits in history
 *   - any `.ts`/`.tsx`/`.js`/`.jsx`/`.py`/`.go`/`.rs` file in the repo root
 *
 * Any 2 signals → brownfield. Otherwise → greenfield.
 */
import { execFileSync } from 'node:child_process';
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
import { join } from 'node:path';
/** @typedef {'greenfield' | 'brownfield'} ProjectArchetype */
/**
 * @typedef {Object} ArchetypeResult
 * @property {ProjectArchetype} type
 * @property {string[]} signals  Human-readable evidence lines ready for display.
 */
const CODE_EXTENSIONS = new Set([
    '.ts',
    '.tsx',
    '.js',
    '.jsx',
    '.mjs',
    '.cjs',
    '.py',
    '.go',
    '.rs',
    '.rb',
    '.java',
    '.kt',
    '.swift',
    '.php',
]);
/**
 * Count git commits in a repo, capped for speed. Returns 0 if not a git
 * repo or git isn't installed.
 *
 * @param {string} dir
 * @returns {number}
 */
function countGitCommits(dir) {
    try {
        const out = execFileSync('git', ['-C', dir, 'rev-list', '--count', 'HEAD'], {
            encoding: 'utf-8',
            stdio: ['ignore', 'pipe', 'ignore'],
            timeout: 2000,
        }).trim();
        const n = Number.parseInt(out, 10);
        return Number.isFinite(n) ? n : 0;
    }
    catch {
        return 0;
    }
}
/**
 * Whether a package.json in `dir` has at least one dependency.
 *
 * @param {string} dir
 * @returns {boolean}
 */
function packageHasDeps(dir) {
    const p = join(dir, 'package.json');
    if (!existsSync(p))
        return false;
    try {
        const pkg = JSON.parse(readFileSync(p, 'utf-8'));
        const deps = Object.keys(pkg.dependencies ?? {});
        const devDeps = Object.keys(pkg.devDependencies ?? {});
        return deps.length + devDeps.length > 0;
    }
    catch {
        return false;
    }
}
/**
 * Whether the repo root contains at least one source file with a known
 * code extension.
 *
 * @param {string} dir
 * @returns {boolean}
 */
function hasRootCodeFile(dir) {
    try {
        for (const entry of readdirSync(dir, { withFileTypes: true })) {
            if (!entry.isFile())
                continue;
            const dot = entry.name.lastIndexOf('.');
            if (dot < 0)
                continue;
            if (CODE_EXTENSIONS.has(entry.name.slice(dot).toLowerCase()))
                return true;
        }
    }
    catch {
        // unreadable dir — treat as no signal
    }
    return false;
}
/**
 * Safe directory existence check.
 *
 * @param {string} path
 * @returns {boolean}
 */
function dirExists(path) {
    try {
        return existsSync(path) && statSync(path).isDirectory();
    }
    catch {
        return false;
    }
}
/**
 * Detect whether the project at `dir` is greenfield (empty/new) or
 * brownfield (existing code). The heuristic is intentionally generous:
 * 2 positive signals flip to brownfield.
 *
 * @param {string} dir
 * @returns {ArchetypeResult}
 */
export function detectArchetype(dir) {
    const signals = [];
    if (dirExists(join(dir, 'src'))) {
        signals.push('src/ directory exists');
    }
    if (dirExists(join(dir, 'tests')) || dirExists(join(dir, '__tests__'))) {
        signals.push('existing test directory');
    }
    if (packageHasDeps(dir)) {
        signals.push('package.json has dependencies');
    }
    const commits = countGitCommits(dir);
    if (commits >= 10) {
        signals.push(`git history (${commits} commits)`);
    }
    if (hasRootCodeFile(dir)) {
        signals.push('source files at repo root');
    }
    const type = signals.length >= 2 ? 'brownfield' : 'greenfield';
    return { type, signals };
}
//# sourceMappingURL=archetype.mjs.map