// Planu — Dead code scanner (SPEC-482)
// Finds exported symbols that are never imported anywhere in the project.
import { readFileSync } from 'node:fs';
/** Extract all `export` statement names from a file's source. */
function extractExports(source, file) {
    const results = [];
    const lines = source.split('\n');
    lines.forEach((lineText, idx) => {
        // export function foo / export class Foo / export const foo / export type Foo
        const match = /^export\s+(?:async\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)/.exec(lineText);
        if (match?.[1] !== undefined) {
            // Skip default exports and re-exports
            results.push({ name: match[1], file, line: idx + 1 });
        }
        // export { foo, bar }
        const namedMatch = /^export\s*\{([^}]+)\}/.exec(lineText);
        if (namedMatch?.[1] !== undefined) {
            const names = namedMatch[1].split(',').map((n) => n
                .trim()
                .split(/\s+as\s+/)[0]
                ?.trim() ?? '');
            names.forEach((name) => {
                if (name.length > 0) {
                    results.push({ name, file, line: idx + 1 });
                }
            });
        }
    });
    return results;
}
/** Build a set of all imported names across all project files. */
function collectAllImports(filePaths) {
    const imported = new Set();
    const importRe = /import\s+(?:type\s+)?(?:\{([^}]+)\}|(\w+))\s+from/g;
    for (const fp of filePaths) {
        let source;
        try {
            source = readFileSync(fp, 'utf8');
        }
        catch {
            continue;
        }
        let m;
        importRe.lastIndex = 0;
        while ((m = importRe.exec(source)) !== null) {
            if (m[1] !== undefined) {
                m[1].split(',').forEach((part) => {
                    const name = part
                        .trim()
                        .split(/\s+as\s+/)[0]
                        ?.trim() ?? '';
                    if (name.length > 0) {
                        imported.add(name);
                    }
                });
            }
            else if (m[2] !== undefined) {
                imported.add(m[2]);
            }
        }
        importRe.lastIndex = 0;
    }
    return imported;
}
/** Scan files for exported symbols that are never imported in the project. */
export function scanDeadCode(filePaths) {
    const allImports = collectAllImports(filePaths);
    const candidates = [];
    for (const fp of filePaths) {
        let source;
        try {
            source = readFileSync(fp, 'utf8');
        }
        catch {
            continue;
        }
        const exports = extractExports(source, fp);
        for (const exp of exports) {
            // Skip well-known public entry points
            if (exp.name.startsWith('register') || exp.name === 'default') {
                continue;
            }
            if (!allImports.has(exp.name)) {
                candidates.push({
                    file: fp,
                    line: exp.line,
                    category: 'dead-code',
                    severity: 'medium',
                    description: `Export \`${exp.name}\` is never imported anywhere in the project.`,
                    suggestion: `Delete \`${exp.name}\` or make it internal (remove \`export\`).`,
                });
            }
        }
    }
    return candidates;
}
//# sourceMappingURL=dead-code-scanner.js.map