// Planu — SPEC-051: React 19 + Next.js 16 stack detection
import { readFile, access } from 'node:fs/promises';
import { join } from 'node:path';
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
async function fileExists(basePath, relativePath) {
    try {
        await access(join(basePath, relativePath));
        return true;
    }
    catch {
        return false;
    }
}
async function readJsonFile(filePath) {
    try {
        const content = await readFile(filePath, 'utf-8');
        return JSON.parse(content);
    }
    catch {
        return null;
    }
}
async function readTextFile(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return null;
    }
}
// ---------------------------------------------------------------------------
// React version detection
// ---------------------------------------------------------------------------
function parseReactVersion(version) {
    if (version.startsWith('19') || version.startsWith('^19') || version.startsWith('~19')) {
        return '19';
    }
    if (version.startsWith('18') || version.startsWith('^18') || version.startsWith('~18')) {
        return '18';
    }
    if (version.startsWith('17') || version.startsWith('^17') || version.startsWith('~17')) {
        return '17';
    }
    if (version.startsWith('16') || version.startsWith('^16') || version.startsWith('~16')) {
        return '16';
    }
    return 'unknown';
}
async function detectReactVersion(projectPath) {
    const pkg = await readJsonFile(join(projectPath, 'package.json'));
    if (!pkg) {
        return 'unknown';
    }
    const deps = pkg.dependencies ?? {};
    const devDeps = pkg.devDependencies ?? {};
    const allDeps = { ...deps, ...devDeps };
    const reactVersion = allDeps.react;
    if (!reactVersion) {
        return 'unknown';
    }
    return parseReactVersion(reactVersion);
}
// ---------------------------------------------------------------------------
// Next.js version detection
// ---------------------------------------------------------------------------
function parseNextjsVersion(version) {
    if (version.startsWith('16') || version.startsWith('^16') || version.startsWith('~16')) {
        return '16';
    }
    if (version.startsWith('15') || version.startsWith('^15') || version.startsWith('~15')) {
        return '15';
    }
    if (version.startsWith('14') || version.startsWith('^14') || version.startsWith('~14')) {
        return '14';
    }
    if (version.startsWith('13') || version.startsWith('^13') || version.startsWith('~13')) {
        return '13';
    }
    return 'unknown';
}
async function detectNextjsVersion(projectPath) {
    const pkg = await readJsonFile(join(projectPath, 'package.json'));
    if (!pkg) {
        return 'unknown';
    }
    const deps = pkg.dependencies ?? {};
    const devDeps = pkg.devDependencies ?? {};
    const allDeps = { ...deps, ...devDeps };
    const nextVersion = allDeps.next;
    if (!nextVersion) {
        return 'unknown';
    }
    return parseNextjsVersion(nextVersion);
}
// ---------------------------------------------------------------------------
// Router mode detection
// ---------------------------------------------------------------------------
async function detectRouterMode(projectPath) {
    const hasApp = await fileExists(projectPath, 'app');
    const hasPages = await fileExists(projectPath, 'pages');
    // Also check src/ subdirectory (common Next.js project layout)
    const hasAppSrc = await fileExists(projectPath, 'src/app');
    const hasPagesSrc = await fileExists(projectPath, 'src/pages');
    const appRouter = hasApp || hasAppSrc;
    const pagesRouter = hasPages || hasPagesSrc;
    if (appRouter && pagesRouter) {
        return 'hybrid';
    }
    if (appRouter) {
        return 'app';
    }
    if (pagesRouter) {
        return 'pages';
    }
    return 'none';
}
// ---------------------------------------------------------------------------
// React Compiler detection
// ---------------------------------------------------------------------------
async function detectReactCompiler(projectPath) {
    // Check package.json devDependencies for babel-plugin-react-compiler
    const pkg = await readJsonFile(join(projectPath, 'package.json'));
    if (pkg) {
        const devDeps = pkg.devDependencies ?? {};
        const deps = pkg.dependencies ?? {};
        const allDeps = { ...deps, ...devDeps };
        if ('babel-plugin-react-compiler' in allDeps) {
            return true;
        }
    }
    // Check next.config.ts / next.config.js for experimental.reactCompiler
    for (const configFile of ['next.config.ts', 'next.config.js', 'next.config.mjs']) {
        const content = await readTextFile(join(projectPath, configFile));
        if (content !== null && /reactCompiler\s*:\s*true/.test(content)) {
            return true;
        }
    }
    // Check babel.config.js / .babelrc for react-compiler plugin
    for (const babelFile of ['babel.config.js', 'babel.config.ts', '.babelrc', '.babelrc.js']) {
        const content = await readTextFile(join(projectPath, babelFile));
        if (content?.includes('react-compiler')) {
            return true;
        }
    }
    return false;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Detect React and Next.js versions and features from project files.
 * S1-C1, S1-C2, S1-C3
 */
export async function detectReactStack(projectPath) {
    const [reactVersion, nextjsVersion, routerMode, reactCompilerEnabled] = await Promise.all([
        detectReactVersion(projectPath),
        detectNextjsVersion(projectPath),
        detectRouterMode(projectPath),
        detectReactCompiler(projectPath),
    ]);
    const serverComponentsEnabled = nextjsVersion !== 'unknown' && routerMode === 'app';
    return {
        reactVersion,
        nextjsVersion,
        routerMode,
        reactCompilerEnabled,
        serverComponentsEnabled,
    };
}
// Re-export helpers for testing
export { parseReactVersion, parseNextjsVersion };
//# sourceMappingURL=react-detector.js.map