// engine/solid-check/index.ts — SPEC-962 SOLID Check Engine
import { readFile } from 'node:fs/promises';
import { glob } from 'glob';
import { checkSolid } from '../auditor-architecture.js';
/**
 * Gather source files matching common patterns.
 */
async function gatherFiles(projectPath, exclude) {
    const patterns = [
        'src/**/*.{ts,tsx,js,jsx}',
        'app/**/*.{ts,tsx,js,jsx}',
        'pages/**/*.{ts,tsx,js,jsx}',
        'api/**/*.{ts,tsx,js,jsx}',
    ];
    const files = [];
    for (const pattern of patterns) {
        const matches = await glob(pattern, {
            cwd: projectPath,
            absolute: true,
            ignore: exclude,
        });
        files.push(...matches);
    }
    return [...new Set(files)];
}
/**
 * Compute per-principle scores from violations.
 */
function computePrincipleScores(violations) {
    const principleMap = new Map();
    for (const v of violations) {
        const existing = principleMap.get(v.principle);
        const deduction = v.severity === 'error' ? 15 : v.severity === 'warning' ? 8 : 3;
        if (existing) {
            existing.count += 1;
            existing.deductions += deduction;
        }
        else {
            principleMap.set(v.principle, { count: 1, deductions: deduction });
        }
    }
    const scores = Array.from(principleMap.entries()).map(([principle, { count, deductions }]) => ({
        principle,
        score: Math.max(0, 100 - deductions),
        violationCount: count,
    }));
    if (scores.length === 0) {
        const allPrinciples = [
            'Single Responsibility Principle',
            'Open/Closed Principle',
            'Liskov Substitution Principle',
            'Interface Segregation Principle',
            'Dependency Inversion Principle',
        ];
        for (const p of allPrinciples) {
            scores.push({ principle: p, score: 100, violationCount: 0 });
        }
    }
    return scores;
}
/**
 * Run SOLID checks on all source files in a project.
 */
export async function runSolidCheck(input) {
    const { projectPath, exclude = ['node_modules/**', '.git/**', 'dist/**'] } = input;
    const uniqueFiles = await gatherFiles(projectPath, exclude);
    const violations = [];
    for (const file of uniqueFiles) {
        let content;
        try {
            content = await readFile(file, 'utf-8');
        }
        catch {
            continue;
        }
        const lines = content.split('\n');
        const ext = file.slice(file.lastIndexOf('.'));
        const findings = checkSolid(file, content, lines, ext);
        for (const f of findings) {
            violations.push({
                rule: f.rule,
                principle: f.reference ?? 'SOLID',
                message: f.message,
                filePath: f.file,
                line: f.line ?? 0,
                severity: f.severity === 'critical' ? 'error' : f.severity,
                suggestion: f.suggestion,
            });
        }
    }
    const errorCount = violations.filter((v) => v.severity === 'error').length;
    const warningCount = violations.filter((v) => v.severity === 'warning').length;
    const infoCount = violations.filter((v) => v.severity === 'info').length;
    const principleScores = computePrincipleScores(violations);
    const overallScore = Math.round(principleScores.reduce((sum, ps) => sum + ps.score, 0) / principleScores.length);
    const report = {
        pass: errorCount === 0,
        score: overallScore,
        filesScanned: uniqueFiles.length,
        totalViolations: violations.length,
        errorCount,
        warningCount,
        infoCount,
        violations,
        principleScores,
    };
    const humanSummary = buildHumanSummary(report);
    return { report, humanSummary };
}
function buildHumanSummary(report) {
    const lines = [];
    lines.push(`# SOLID Check Report`);
    lines.push('');
    lines.push(`**Result**: ${report.pass ? 'PASS' : 'FAIL'} | **Score**: ${report.score}/100`);
    lines.push(`**Files scanned**: ${report.filesScanned}`);
    lines.push(`**Violations**: ${report.totalViolations} (${report.errorCount} errors, ${report.warningCount} warnings, ${report.infoCount} info)`);
    lines.push('');
    if (report.principleScores.length > 0) {
        lines.push('## Principle Scores');
        lines.push('');
        lines.push('| Principle | Score | Violations |');
        lines.push('|-----------|-------|------------|');
        for (const ps of report.principleScores) {
            lines.push(`| ${ps.principle} | ${ps.score}/100 | ${ps.violationCount} |`);
        }
        lines.push('');
    }
    const topErrors = report.violations.filter((v) => v.severity === 'error').slice(0, 5);
    if (topErrors.length > 0) {
        lines.push('## Top Errors');
        lines.push('');
        for (const e of topErrors) {
            lines.push(`- **${e.rule}** in \`${e.filePath}\``);
            lines.push(`  - ${e.message}`);
            lines.push(`  - Suggestion: ${e.suggestion}`);
        }
        lines.push('');
    }
    return lines.join('\n');
}
//# sourceMappingURL=index.js.map