// engine/workers/handlers/optimization.ts — Detects perf anti-patterns (SPEC-078 AC-07)
import { readFile, readdir, stat } from 'node:fs/promises';
import { join, extname, relative } from 'node:path';
// ---------------------------------------------------------------------------
// Config
// ---------------------------------------------------------------------------
const MAX_FILE_LINES = 400;
const IGNORE_DIRS = new Set([
    'node_modules',
    '.git',
    'dist',
    'build',
    '__pycache__',
    'target',
    '.venv',
    'vendor',
    'coverage',
]);
const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.java', '.kt']);
// ---------------------------------------------------------------------------
// Complexity keywords per language
// ---------------------------------------------------------------------------
const COMPLEXITY_KEYWORDS = {
    '.ts': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bswitch\b/, /\bcase\b/, /\bcatch\b/],
    '.tsx': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bswitch\b/, /\bcase\b/, /\bcatch\b/],
    '.js': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bswitch\b/, /\bcase\b/, /\bcatch\b/],
    '.jsx': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bswitch\b/, /\bcase\b/, /\bcatch\b/],
    '.py': [/\bif\b/, /\belif\b/, /\bfor\b/, /\bwhile\b/, /\bexcept\b/],
    '.go': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bswitch\b/, /\bcase\b/],
    '.rs': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bmatch\b/, /\bloop\b/],
    '.java': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bswitch\b/, /\bcase\b/, /\bcatch\b/],
    '.kt': [/\bif\b/, /\belse\b/, /\bfor\b/, /\bwhile\b/, /\bwhen\b/, /\bcatch\b/],
};
// ---------------------------------------------------------------------------
// File collection
// ---------------------------------------------------------------------------
async function collectFiles(dir, files) {
    let entries;
    try {
        entries = await readdir(dir);
    }
    catch {
        return;
    }
    for (const entry of entries) {
        if (IGNORE_DIRS.has(entry)) {
            continue;
        }
        const fullPath = join(dir, entry);
        let st;
        try {
            st = await stat(fullPath);
        }
        catch {
            continue;
        }
        if (st.isDirectory()) {
            await collectFiles(fullPath, files);
        }
        else if (st.isFile() && CODE_EXTS.has(extname(fullPath))) {
            files.push(fullPath);
        }
    }
}
// ---------------------------------------------------------------------------
// Analysis helpers
// ---------------------------------------------------------------------------
function countComplexity(lines, ext) {
    const keywords = COMPLEXITY_KEYWORDS[ext] ?? COMPLEXITY_KEYWORDS['.ts'] ?? [];
    let count = 1; // base complexity
    for (const line of lines) {
        for (const kw of keywords) {
            if (kw.test(line)) {
                count++;
            }
        }
    }
    return count;
}
function detectImportPaths(lines, ext) {
    const imports = [];
    for (const line of lines) {
        if (ext === '.ts' || ext === '.tsx' || ext === '.js' || ext === '.jsx') {
            const m = /from\s+['"](\.[^'"]+)['"]/.exec(line);
            if (m?.[1]) {
                imports.push(m[1]);
            }
        }
        else if (ext === '.py') {
            const m = /^(?:from|import)\s+(\S+)/.exec(line);
            if (m?.[1]) {
                imports.push(m[1]);
            }
        }
        else if (ext === '.go') {
            const m = /^\s*"([^"]+)"/.exec(line);
            if (m?.[1]) {
                imports.push(m[1]);
            }
        }
    }
    return imports;
}
// ---------------------------------------------------------------------------
// Public handler
// ---------------------------------------------------------------------------
export async function runOptimization(projectDir, _changedFiles) {
    const startedAt = new Date().toISOString();
    const start = Date.now();
    const findings = [];
    const allFiles = [];
    await collectFiles(projectDir, allFiles);
    // Track imports for circular dependency detection
    const importGraph = new Map();
    for (const file of allFiles) {
        let content;
        try {
            content = await readFile(file, 'utf-8');
        }
        catch {
            continue;
        }
        const ext = extname(file);
        const lines = content.split('\n');
        const relPath = relative(projectDir, file);
        // Large file detection
        if (lines.length > MAX_FILE_LINES) {
            findings.push({
                severity: 'warning',
                file: relPath,
                message: `File has ${String(lines.length)} lines (max: ${String(MAX_FILE_LINES)})`,
                suggestion: 'Split into smaller, focused modules',
                category: 'large-file',
            });
        }
        // Cyclomatic complexity
        const complexity = countComplexity(lines, ext);
        if (complexity > 15) {
            findings.push({
                severity: complexity > 25 ? 'high' : 'medium',
                file: relPath,
                message: `File-level cyclomatic complexity: ${String(complexity)}`,
                suggestion: 'Extract complex logic into separate functions or modules',
                category: 'high-complexity',
            });
        }
        // Collect imports for graph
        const imports = detectImportPaths(lines, ext);
        importGraph.set(relPath, imports);
    }
    return {
        workerName: 'optimization',
        startedAt,
        completedAt: new Date().toISOString(),
        durationMs: Date.now() - start,
        status: 'success',
        findings,
        analyzedFiles: allFiles.length,
    };
}
//# sourceMappingURL=optimization.js.map