import { readFile } from 'node:fs/promises';
import { collectFiles } from './file-collector.js';
import { calculateScore } from './score-calculator.js';
import { typescriptDetector } from './detectors/typescript-detector.js';
import { pythonDetector } from './detectors/python-detector.js';
import { goDetector } from './detectors/go-detector.js';
import { rustDetector } from './detectors/rust-detector.js';
import { javaDetector } from './detectors/java-detector.js';
import { frameworkDetector } from './detectors/framework-detector.js';
import { fastReadFiles } from '../core-bridge.js';
export { fixCrashRisks } from './auto-fixer/index.js';
const ALL_DETECTORS = [
    typescriptDetector,
    pythonDetector,
    goDetector,
    rustDetector,
    javaDetector,
    frameworkDetector,
];
/**
 * Scans a project for crash risks and returns a SafetyReport.
 * @param projectPath - absolute path to the project root
 * @param stackHint - optional list of languages to restrict scanning (e.g. ['TypeScript'])
 */
export async function scanCrashRisks(projectPath, stackHint) {
    const startTime = Date.now();
    const { files, detectedStack } = await collectFiles(projectPath, stackHint);
    const allRisks = await scanFiles(files, detectedStack);
    const score = calculateScore(allRisks);
    const scanDurationMs = Date.now() - startTime;
    return {
        score,
        risks: allRisks,
        scannedFiles: files.length,
        detectedStack,
        scanDurationMs,
    };
}
async function scanFiles(files, detectedStack) {
    const applicableDetectors = selectDetectors(detectedStack);
    const fileContents = fastReadFiles(files);
    const seen = new Set(fileContents.map((file) => file.path));
    const results = fileContents.map(({ path, content }) => detectRisksInContent(path, content, applicableDetectors));
    const unreadByBridge = files.filter((file) => !seen.has(file));
    const fallbackResults = await Promise.all(unreadByBridge.map(async (file) => {
        try {
            const content = await readFile(file, 'utf-8');
            return detectRisksInContent(file, content, applicableDetectors);
        }
        catch {
            return [];
        }
    }));
    return [...results, ...fallbackResults].flat();
}
function detectRisksInContent(path, content, applicableDetectors) {
    const fileDetectors = applicableDetectors.filter((d) => d.fileExtensions.some((ext) => path.endsWith(ext)));
    const risks = [];
    for (const detector of fileDetectors) {
        try {
            const found = detector.detect(path, content);
            risks.push(...found);
        }
        catch {
            // Detector error: skip silently
        }
    }
    return risks;
}
function selectDetectors(detectedStack) {
    if (detectedStack.length === 0) {
        return ALL_DETECTORS;
    }
    return ALL_DETECTORS.filter((detector) => {
        if (detector.language === 'multi') {
            return true;
        }
        return detectedStack.includes(detector.language);
    });
}
//# sourceMappingURL=index.js.map