import fs from "node:fs/promises";
import path from "node:path";
import { checkSimplicityFirst, checkSurgicalChanges } from "./core_engineering_principles.js";
import { debugLog } from "../core/logger.js";
debugLog("code_reviewer: 代码审查引擎模块已加载");
/** 摘要缓存实例（模块级别，跨任务持久） */
const summaryCache = new Map();
const MAX_CACHE_ENTRIES = 500;
/**
 * 为白盒审查项生成压缩摘要并缓存。
 * 摘要提取: 文件名 + 维度 + 规则描述，压缩为一句话。
 *
 * @param taskId - 任务 ID
 * @param findings - 审查发现列表
 * @param classified - 信任分级后的发现列表
 */
function cacheWhiteBoxSummary(taskId, findings, classified) {
    const entries = [];
    for (let i = 0; i < classified.length; i++) {
        if (classified[i].trust_level === "white_box") {
            const f = findings[i];
            const summary = `[${f.file.split("/").pop()}:${f.line ?? "?"}] ${f.dimension}: ${f.title}`;
            entries.push({
                original_index: i,
                file: f.file,
                compressed_summary: summary,
                cached_at: Date.now(),
            });
        }
    }
    // 防止内存泄漏: 限制缓存大小
    if (summaryCache.size > MAX_CACHE_ENTRIES) {
        const oldest = [...summaryCache.entries()]
            .sort((a, b) => a[1][0]?.cached_at ?? 0 - (b[1][0]?.cached_at ?? 0))[0];
        if (oldest)
            summaryCache.delete(oldest[0]);
    }
    if (entries.length > 0) {
        summaryCache.set(taskId, entries);
    }
}
/**
 * 回溯渲染: 当抽检哨兵升级白盒为灰盒时，渲染前置折叠任务的摘要流。
 * 返回所有已缓存的白盒摘要，供人类快速回溯。
 *
 * @param taskId - 任务 ID
 * @returns 白盒摘要列表，无缓存时返回空数组
 */
export function renderSummaryBacktrace(taskId) {
    debugLog(`代码审查: 回溯渲染白盒摘要 — taskId: ${taskId}`);
    const entries = summaryCache.get(taskId);
    if (!entries || entries.length === 0) {
        debugLog("代码审查: 白盒摘要缓存未命中");
        return [];
    }
    debugLog(`代码审查: 白盒摘要回溯完成 — ${entries.length} 条`);
    return entries.map((e) => e.compressed_summary);
}
/**
 * 机制 3: 对审查发现进行信任分级路由。
 * 白盒 -> 建议跳过（CRUD/符合模式），灰盒 -> 建议审查（核心算法/安全），黑盒 -> 强制审查（非标逻辑）
 *
 * @param findings - 审查发现列表
 * @param knowledgeIndex - 可选的知识库索引管理器
 * @param changedFiles - 可选的变更文件列表
 * @param fileContents - 可选的文件内容映射
 * @param taskId - 可选的任务 ID，用于摘要缓存
 * @returns 分级后的发现列表、汇总摘要和抽检回溯
 */
function classifyFindingsByTrust(findings, knowledgeIndex, fileContents, taskId) {
    // 获取知识库中的 review_rule 条目用于匹配
    const knowledgeRules = knowledgeIndex
        ? knowledgeIndex.query({ type: "review_rule", limit: 50 })
        : [];
    let whiteCount = 0;
    let grayCount = 0;
    let blackCount = 0;
    const classified = findings.map((f) => {
        const { level, reason } = determineTrustLevel(f, knowledgeRules, fileContents);
        if (level === "white_box")
            whiteCount++;
        else if (level === "gray_box")
            grayCount++;
        else
            blackCount++;
        return { ...f, trust_level: level, trust_reason: reason };
    });
    // 抽检哨兵: 每处理 10 个白盒项，强制随机升级 1 个为灰盒，防止自动化偏见
    // 维度5: 升级时同时渲染前置白盒摘要流，供人工回溯
    let spotCheckBacktrace;
    if (whiteCount >= 10) {
        const whiteIndices = classified
            .map((f, i) => f.trust_level === "white_box" ? i : -1)
            .filter((i) => i >= 0);
        if (whiteIndices.length > 0) {
            const spotIdx = whiteIndices[Math.floor(Math.random() * whiteIndices.length)];
            classified[spotIdx] = {
                ...classified[spotIdx],
                trust_level: "gray_box",
                trust_reason: "⚡ 抽检哨兵: 随机抽检项，防止模式误判。请确认系统未产生错误分类",
            };
            whiteCount--;
            grayCount++;
            // 回溯: 渲染所有白盒摘要
            spotCheckBacktrace = classified
                .filter((c) => c.trust_level === "white_box")
                .map((c) => {
                const orig = findings[classified.indexOf(c)];
                return `[${orig.file.split("/").pop()}:${orig.line ?? "?"}] ${orig.dimension}: ${orig.title}`;
            });
        }
    }
    // 维度5: 缓存白盒摘要（供未来抽检回溯使用）
    cacheWhiteBoxSummary(taskId ?? "default", findings, classified);
    const recommendation = blackCount > 0
        ? `强制审查 ${blackCount} 项黑盒发现（无知识库支撑的非标逻辑）`
        : grayCount > 0
            ? `建议审查 ${grayCount} 项灰盒发现（核心算法/安全边界相关${whiteCount >= 10 ? "，含抽检哨兵" : ""}）`
            : `全部为白盒发现，建议跳过详细审查`;
    return {
        classified,
        summary: {
            white_box_count: whiteCount,
            gray_box_count: grayCount,
            black_box_count: blackCount,
            recommendation,
        },
        spot_check_backtrace: spotCheckBacktrace,
    };
}
/**
 * 判断单条发现的信任级别。
 * @param finding - 审查发现
 * @param knowledgeRules - 知识库中的审查规则
 * @param _fileContents - 文件内容映射（预留参数）
 * @returns 信任级别和理由
 */
function determineTrustLevel(finding, knowledgeRules, _fileContents) {
    // 黑盒判定: 无知识库支撑的 critical 发现
    if (finding.severity === "critical") {
        const hasKnowledgeSupport = knowledgeRules.some((rule) => rule.body && rule.body.includes(finding.title));
        if (!hasKnowledgeSupport) {
            return {
                level: "black_box",
                reason: "严重问题且无知识库规则支撑，属于非标逻辑",
            };
        }
    }
    // 灰盒判定: 安全维度 或 architecture 维度
    if (finding.dimension === "security" || finding.dimension === "architecture") {
        return {
            level: "gray_box",
            reason: `涉及${finding.dimension === "security" ? "安全边界" : "架构"}，建议审查`,
        };
    }
    // 灰盒判定: 严重度为 warning 的性能问题
    if (finding.dimension === "performance" && finding.severity === "warning") {
        return {
            level: "gray_box",
            reason: "性能警告，涉及核心逻辑效率",
        };
    }
    // 白盒判定: 其余所有（quality/info/debt 等）
    return {
        level: "white_box",
        reason: "常规质量/技术债务检查项，符合已知模式",
    };
}
/**
 * 执行代码审查 — 对变更文件逐一进行质量、安全、性能、技术债务和知识规则检查。
 * @param input - 审查输入参数，包含变更文件列表、项目路径、配置和分类结果等
 * @param tracker - 可选的技术债务追踪器，审查中发现的技术债务会自动记录
 * @returns 代码审查结果，包含发现列表、严重度统计和总体评估
 */
export async function reviewCode(input, tracker) {
    const { changedFiles, projectPath, classification, fileContents, knowledgeIndex, review_role, uncertainty_triggers } = input;
    debugLog(`code_reviewer: 开始代码审查，${changedFiles.length} 个变更文件`);
    // 能力 5: 角色检测 — 默认自审，自审模式下置信度降低 0.2
    const role = review_role ?? "self_review";
    const selfReviewConfidencePenalty = role === "self_review" ? -0.2 : 0;
    // 能力 1: 风险调整审查 — 高/中风险任务启用加强审查
    const riskAdjusted = classification?.risk === "high" || classification?.risk === "medium";
    // 跳过逻辑: hotfix 类型自动跳过审查以加速修复
    if (classification?.task_type === "hotfix") {
        debugLog("code_reviewer: hotfix 类型，跳过代码审查");
        return {
            task_id: "",
            findings: [],
            summary: { total: 0, by_dimension: emptyDimension(), by_severity: emptySeverity(), debt_items: 0 },
            overall_assessment: "紧急修复场景，跳过代码审查",
            skip_reason: "hotfix 类型自动跳过",
        };
    }
    if (changedFiles.length === 0) {
        debugLog("code_reviewer: 无变更文件，跳过审查");
        return {
            task_id: "",
            findings: [],
            summary: { total: 0, by_dimension: emptyDimension(), by_severity: emptySeverity(), debt_items: 0 },
            overall_assessment: "无变更文件，跳过审查",
            skip_reason: "无变更文件",
        };
    }
    // 读取文件内容
    const contents = fileContents ?? await readFiles(changedFiles, projectPath);
    // 逐文件审查
    const allFindings = [];
    let findingIdx = 1;
    for (const filePath of changedFiles) {
        const content = contents[filePath] ?? "";
        const lines = content.split("\n");
        const ext = path.extname(filePath);
        // 质量检查
        allFindings.push(...checkQuality(filePath, content, lines, ext, findingIdx));
        findingIdx += allFindings.length;
        // 安全检查
        allFindings.push(...checkSecurity(filePath, content, lines, ext, findingIdx));
        findingIdx += allFindings.length;
        // 性能检查
        allFindings.push(...checkPerformance(filePath, content, lines, ext, findingIdx));
        findingIdx += allFindings.length;
        // 技术债务检查
        allFindings.push(...checkDebt(filePath, content, lines, findingIdx));
        findingIdx += allFindings.length;
        // 知识驱动规则检查
        if (knowledgeIndex) {
            allFindings.push(...checkKnowledgeRules(filePath, content, lines, ext, knowledgeIndex, findingIdx, input.task_stage));
            findingIdx += allFindings.length;
        }
    }
    // : Simplicity/Surgical 原则检查 — 发现过度工程和 scope 外修改
    const principleCtx = {
        changed_files: changedFiles,
        declared_scope: input.declared_scope ?? [],
    };
    const simplicityResult = checkSimplicityFirst(principleCtx);
    if (simplicityResult.status === "failed") {
        for (const finding of simplicityResult.findings) {
            allFindings.push(makeFinding(findingIdx++, "all", undefined, "architecture", "warning", "[Simplicity First] 过度工程", finding, "减少不必要的复杂度引入"));
        }
    }
    const surgicalResult = checkSurgicalChanges(principleCtx);
    if (surgicalResult.status === "failed") {
        for (const finding of surgicalResult.findings) {
            allFindings.push(makeFinding(findingIdx++, "all", undefined, "quality", "warning", "[Surgical Changes] Scope 外修改", finding, "只修改目标范围内的文件"));
        }
    }
    // 重新编号
    const findings = allFindings.map((f, i) => ({ ...f, id: `R-${String(i + 1).padStart(3, "0")}` }));
    // 记录技术债务
    if (tracker) {
        for (const finding of findings) {
            if (finding.is_debt) {
                await tracker.recordDebt(finding, "");
            }
        }
    }
    // 汇总
    const byDimension = emptyDimension();
    const bySeverity = emptySeverity();
    let debtCount = 0;
    for (const f of findings) {
        byDimension[f.dimension]++;
        bySeverity[f.severity]++;
        if (f.is_debt)
            debtCount++;
    }
    // 能力 4: 检查不确定性触发条件是否被绕过
    const uncertaintyViolations = [];
    if (uncertainty_triggers && uncertainty_triggers.length > 0) {
        for (const trigger of uncertainty_triggers) {
            uncertaintyViolations.push(`${trigger.trigger_type}: ${trigger.description} — 未确认`);
        }
    }
    // 机制 3: 认知减负路由 — 按信任分级过滤审查发现
    const { classified: trustClassified, summary: trustSummary } = classifyFindingsByTrust(findings, knowledgeIndex, fileContents, input.task_id);
    debugLog(`code_reviewer: 审查完成 — 共 ${findings.length} 项发现（白盒 ${trustSummary.white_box_count}，灰盒 ${trustSummary.gray_box_count}，黑盒 ${trustSummary.black_box_count}）`);
    return {
        task_id: "",
        findings: trustClassified,
        summary: { total: findings.length, by_dimension: byDimension, by_severity: bySeverity, debt_items: debtCount },
        overall_assessment: formatAssessment(findings.length, bySeverity, role, riskAdjusted),
        review_role: role,
        confidence_adjustment: selfReviewConfidencePenalty,
        disputes: [],
        uncertainty_violations: uncertaintyViolations.length > 0 ? uncertaintyViolations : undefined,
        risk_adjusted: riskAdjusted,
        trust_classification: trustSummary,
    };
}
/**
 * 质量维度检查 — 检测 console.log 和 TypeScript any 类型使用。
 * @param filePath - 文件路径
 * @param content - 文件内容
 * @param lines - 文件行数组
 * @param ext - 文件扩展名
 * @param startIdx - 发现编号起始值
 * @returns 质量发现列表
 */
function checkQuality(filePath, _content, lines, ext, startIdx) {
    const findings = [];
    let idx = startIdx;
    // console.log 检测（跳过测试文件，测试中 console.log 可接受）
    if (!/\.test\.|\.spec\./.test(filePath)) {
        lines.forEach((line, i) => {
            if (/console\.log\(/.test(line)) {
                findings.push(makeFinding(idx++, filePath, i + 1, "quality", "warning", "生产代码中包含 console.log", `第 ${i + 1} 行使用了 console.log，应移除或替换为日志框架`, "使用项目的日志工具替代 console.log"));
            }
        });
    }
    // TypeScript any 类型检测 — 三种 any 用法: 类型注解(: any)、断言(as any)、泛型(<any>)
    if (ext === ".ts" || ext === ".tsx") {
        lines.forEach((line, i) => {
            if (/: any\b/.test(line) || /as any/.test(line) || /<any>/.test(line)) {
                findings.push(makeFinding(idx++, filePath, i + 1, "quality", "info", "使用了 any 类型", `第 ${i + 1} 行使用了 TypeScript any 类型`, "定义明确的类型接口"));
            }
        });
    }
    return findings;
}
/**
 * 安全维度检查 — 检测 SQL 拼接、eval/Function 构造器和 innerHTML 赋值。
 * @param filePath - 文件路径
 * @param content - 文件内容
 * @param lines - 文件行数组
 * @param ext - 文件扩展名
 * @param startIdx - 发现编号起始值
 * @returns 安全发现列表
 */
function checkSecurity(filePath, _content, lines, ext, startIdx) {
    const findings = [];
    let idx = startIdx;
    // SQL 拼接检测 — 匹配含 SQL 关键字且使用字符串拼接(+/${}/%s)的行，仅检查 Java/TS 文件
    if (ext === ".java" || ext === ".ts") {
        lines.forEach((line, i) => {
            if (/["'`]SELECT|INSERT|UPDATE|DELETE/i.test(line) && (/\+/.test(line) || /\$\{/.test(line) || /%s/.test(line))) {
                findings.push(makeFinding(idx++, filePath, i + 1, "security", "critical", "疑似 SQL 拼接", `第 ${i + 1} 行可能存在 SQL 字符串拼接`, "使用参数化查询或 ORM 方法"));
            }
        });
    }
    // eval/Function 构造器检测 — 动态代码执行，任意文件类型均检查
    lines.forEach((line, i) => {
        if (/\beval\s*\(/.test(line) || /\bFunction\s*\(/.test(line)) {
            findings.push(makeFinding(idx++, filePath, i + 1, "security", "critical", "使用了 eval 或 Function 构造器", `第 ${i + 1} 行使用了动态代码执行`, "避免 eval，使用安全的替代方案"));
        }
    });
    // innerHTML 检测 — XSS 攻击面，仅检查前端文件 (TSX/JSX/HTML)
    if (ext === ".tsx" || ext === ".jsx" || ext === ".html") {
        lines.forEach((line, i) => {
            if (/\.innerHTML\s*=/.test(line)) {
                findings.push(makeFinding(idx++, filePath, i + 1, "security", "warning", "使用了 innerHTML", `第 ${i + 1} 行直接设置 innerHTML，存在 XSS 风险`, "使用 textContent 或安全的 DOM 操作"));
            }
        });
    }
    return findings;
}
/**
 * 性能维度检查 — 检测循环内数据库调用（N+1 问题）和 SELECT * 语句。
 * @param filePath - 文件路径
 * @param content - 文件内容
 * @param lines - 文件行数组
 * @param ext - 文件扩展名
 * @param startIdx - 发现编号起始值
 * @returns 性能发现列表
 */
function checkPerformance(filePath, _content, lines, ext, startIdx) {
    const findings = [];
    let idx = startIdx;
    // 循环内数据库调用检测 — 通过花括号深度追踪 for/while 循环范围，仅检查 Java 文件
    if (ext === ".java") {
        const loopPattern = /(for|while)\s*\(/;
        const dbPattern = /\.(select|insert|update|delete|save|findBy|query)\s*\(/i;
        let braceDepth = 0;
        let loopDepth = -1;
        let loopStart = 0;
        lines.forEach((line, i) => {
            for (const ch of line) {
                if (ch === "{") {
                    braceDepth++;
                }
                else if (ch === "}") {
                    if (loopDepth >= 0 && braceDepth <= loopDepth) {
                        loopDepth = -1;
                    }
                    braceDepth = Math.max(0, braceDepth - 1);
                }
            }
            if (loopPattern.test(line)) {
                loopDepth = braceDepth;
                loopStart = i + 1;
            }
            if (loopDepth >= 0 && dbPattern.test(line)) {
                findings.push(makeFinding(idx++, filePath, i + 1, "performance", "warning", "循环内可能存在数据库调用", `第 ${loopStart} 行循环体内第 ${i + 1} 行调用了数据库方法，可能导致 N+1 问题`, "使用批量查询替代循环内单次查询"));
            }
        });
    }
    // SELECT * 检测 — 返回不必要字段造成资源浪费，任意文件类型均检查
    lines.forEach((line, i) => {
        if (/SELECT\s+\*/i.test(line)) {
            findings.push(makeFinding(idx++, filePath, i + 1, "performance", "info", "使用了 SELECT *", `第 ${i + 1} 行使用了 SELECT *，可能返回不必要的数据`, "明确列出需要的字段"));
        }
    });
    return findings;
}
/**
 * 技术债务维度检查 — 检测 TODO/FIXME/HACK/XXX 标记和过长文件（>500行）。
 * @param filePath - 文件路径
 * @param content - 文件内容
 * @param lines - 文件行数组
 * @param startIdx - 发现编号起始值
 * @returns 技术债务发现列表
 */
function checkDebt(filePath, _content, lines, startIdx) {
    const findings = [];
    let idx = startIdx;
    // TODO/FIXME/HACK/XXX 标记
    lines.forEach((line, i) => {
        const match = line.match(/\b(TODO|FIXME|HACK|XXX)\b/);
        if (match) {
            findings.push({
                ...makeFinding(idx++, filePath, i + 1, "debt", "info", `发现 ${match[1]} 标记`, `第 ${i + 1} 行: ${line.trim().slice(0, 80)}`, undefined),
                is_debt: true,
            });
        }
    });
    // 过长文件
    if (lines.length > 500) {
        findings.push({
            ...makeFinding(idx++, filePath, undefined, "debt", "info", `文件过长（${lines.length} 行）`, `${filePath} 超过 500 行，建议拆分`, "按职责拆分为多个模块"),
            is_debt: true,
        });
    }
    return findings;
}
/**
 * 从知识条目正文中解析审查规则 — 支持格式: `- [ID] 描述 | pattern: /regex/flags | severity: level | scope: scope`
 * @param body - 知识条目正文内容
 * @param fileName - 知识条目文件名，用于推断审查维度
 * @returns 解析后的规则数组，无效规则（如非法正则）自动跳过
 */
function parseRulesFromEntry(body, _fileName) {
    const rules = [];
    if (!body.includes("## 规则"))
        return rules;
    const lines = body.split("\n");
    let inSection = false;
    for (const line of lines) {
        if (line.startsWith("## 规则")) {
            inSection = true;
            continue;
        }
        if (inSection && line.startsWith("## "))
            break;
        if (inSection) {
            // 规则格式: - [ID] 描述 | pattern: regex | severity: level | scope: scope
            const match = line.match(/- \[([A-Z]+-\d+)\]\s*(.+?)(?:\s*\|\s*(.+))?$/);
            if (!match)
                continue;
            const id = match[1];
            const description = match[2].trim();
            const attrs = match[3] || "";
            const patternMatch = attrs.match(/pattern:\s*\/(.+?)\/([gimsuy]*)/);
            const severityMatch = attrs.match(/severity:\s*(info|warning|critical)/);
            const scopeMatch = attrs.match(/scope:\s*(\S+)/);
            if (patternMatch) {
                try {
                    const regex = new RegExp(patternMatch[1], patternMatch[2] || "");
                    rules.push({
                        id,
                        description,
                        pattern: regex,
                        severity: severityMatch?.[1] || "info",
                        scope: scopeMatch?.[1],
                    });
                }
                catch {
                    // 无效正则跳过
                }
            }
        }
    }
    return rules;
}
/**
 * 从知识库加载审查规则并对代码进行匹配检查。
 * @param filePath - 文件路径
 * @param content - 文件内容
 * @param lines - 文件行数组
 * @param ext - 文件扩展名
 * @param knowledgeIndex - 知识库索引管理器
 * @param startIdx - 发现编号起始值
 * @returns 知识规则发现列表（已去重）
 */
function checkKnowledgeRules(filePath, _content, lines, _ext, knowledgeIndex, startIdx, taskStage) {
    const findings = [];
    let idx = startIdx;
    // 查询知识库中所有 review_rule 类型的条目（最多 20 条）
    const stages = taskStage ? [taskStage] : undefined;
    const entries = knowledgeIndex.query({ type: "review_rule", stages, limit: 20 });
    if (entries.length === 0)
        return findings;
    // 根据文件扩展名判断所属端（前端/后端），用于 scope 过滤
    const isFrontend = /\.(tsx?|jsx?|vue|css|scss|html)$/.test(filePath);
    const isTest = /\.test\.|\.spec\./.test(filePath);
    const fileSide = isFrontend ? "frontend" : "backend";
    for (const entry of entries) {
        if (!entry.body)
            continue;
        const rules = parseRulesFromEntry(entry.body, entry.file_path);
        for (const rule of rules) {
            // 跳过测试文件中不适用于测试的规则
            if (isTest && rule.scope === "!test")
                continue;
            // 跳过不适用于当前端的规则
            if (rule.scope && rule.scope !== "backend" && rule.scope !== "frontend" && rule.scope !== fileSide)
                continue;
            if (rule.scope === "backend" && isFrontend)
                continue;
            if (rule.scope === "frontend" && !isFrontend)
                continue;
            // 特殊 scope: "check: lines" — 文件行数检查规则，阈值 300 行
            if (rule.scope === "check: lines") {
                if (lines.length > 300) {
                    findings.push(makeFinding(idx++, filePath, undefined, inferDimension(entry.file_path), rule.severity, `文件过长（${lines.length} 行）`, `${filePath} 超过 300 行，建议按职责拆分`, "按单一职责拆分为多个组件/模块"));
                }
                continue;
            }
            // 逐行正则匹配
            lines.forEach((line, i) => {
                if (rule.pattern.test(line)) {
                    findings.push(makeFinding(idx++, filePath, i + 1, inferDimension(entry.file_path), rule.severity, `[${rule.id}] ${rule.description}`, `第 ${i + 1} 行: ${line.trim().slice(0, 80)}`, `参考知识条目: ${entry.name}`));
                }
                // 重置正则 lastIndex（某些正则有 g 标志）
                rule.pattern.lastIndex = 0;
            });
        }
    }
    // 去重：同一文件+行号+标题末30字符视为重复，保留先出现的发现
    return deduplicateFindings(findings);
}
/** 从文件路径推断审查维度 — 根据路径关键字映射到 quality/security/performance/architecture */
function inferDimension(filePath) {
    if (filePath.includes("security"))
        return "security";
    if (filePath.includes("quality"))
        return "quality";
    if (filePath.includes("performance"))
        return "performance";
    if (filePath.includes("architecture"))
        return "architecture";
    return "quality";
}
/** 发现去重 — 同一文件+行号+标题末30字符视为重复项，仅保留首次出现 */
function deduplicateFindings(findings) {
    const seen = new Map();
    for (const f of findings) {
        const key = `${f.file}:${f.line}:${f.title.slice(-30)}`;
        if (!seen.has(key)) {
            seen.set(key, f);
        }
    }
    return [...seen.values()];
}
/**
 * 构造审查发现对象 — 生成统一格式的 ReviewFinding。
 * @param idx - 发现编号
 * @param file - 文件路径
 * @param line - 行号
 * @param dimension - 审查维度
 * @param severity - 严重度
 * @param title - 发现标题
 * @param description - 详细描述
 * @param suggestion - 可选的修复建议
 * @returns 审查发现对象
 */
function makeFinding(idx, file, line, dimension, severity, title, description, suggestion) {
    return { id: `R-${String(idx).padStart(3, "0")}`, file, line, dimension, severity, title, description, suggestion, is_debt: false };
}
/** 创建全零的维度计数器 */
function emptyDimension() {
    return { quality: 0, security: 0, performance: 0, debt: 0, architecture: 0 };
}
/** 创建全零的严重度计数器 */
function emptySeverity() {
    return { info: 0, warning: 0, critical: 0 };
}
/**
 * 格式化总体评估文本 — 根据发现问题数量和严重度生成中文摘要。
 * @param total - 发现总数
 * @param bySeverity - 各严重度计数
 * @param role - 审查角色，自审模式附加置信度提示
 * @param riskAdjusted - 是否启用风险调整审查
 * @returns 中文格式的评估摘要字符串
 */
function formatAssessment(total, bySeverity, role, riskAdjusted) {
    if (total === 0)
        return "代码审查通过，未发现问题";
    const parts = [];
    if (bySeverity.critical > 0)
        parts.push(`${bySeverity.critical} 个严重问题`);
    if (bySeverity.warning > 0)
        parts.push(`${bySeverity.warning} 个警告`);
    if (bySeverity.info > 0)
        parts.push(`${bySeverity.info} 个提示`);
    let assessment = `共发现 ${total} 项: ${parts.join("，")}`;
    if (role === "self_review") {
        assessment += " | ⚠ 自审模式，置信度已降级";
    }
    if (riskAdjusted) {
        assessment += " | 风险调整审查已启用";
    }
    return assessment;
}
/**
 * 批量读取文件内容 — 无法读取的文件自动跳过（如已被删除）。
 * @param files - 相对于 basePath 的文件路径列表
 * @param basePath - 项目根目录
 * @returns 文件路径到内容的映射
 */
async function readFiles(files, basePath) {
    const contents = {};
    await Promise.all(files.map(async (file) => {
        try {
            contents[file] = await fs.readFile(path.join(basePath, file), "utf-8");
        }
        catch {
            debugLog(`代码审查: 文件读取失败，跳过 — ${path.join(basePath, file)}`);
        }
    }));
    return contents;
}
//# sourceMappingURL=code_reviewer.js.map