import fs from "node:fs/promises";
import fss from "node:fs";
import path from "node:path";
import matter from "gray-matter";
import { debug } from "./core/logger.js";
/**
 * 检测项目代码惯例。
 * @description 优先加载项目中配置的惯例文件（支持 YAML front-matter 格式），
 *              然后逐个分析源文件，识别特定的编码模式。最多返回 10 条惯例。
 * @param filePaths - 待分析的文件路径列表
 * @param projectPath - 项目根目录路径（用于解析相对路径）
 * @param conventionsFile - 惯例配置文件路径（可选）
 * @returns 检测到的惯例列表
 */
export async function detectConventions(filePaths, projectPath, conventionsFile) {
    debug("convention_detector", "detectConventions() 开始执行");
    const conventions = [];
    // 优先加载项目中配置的惯例文件（YAML front-matter 格式，conventions 字段为数组）
    if (conventionsFile) {
        const convPath = path.resolve(projectPath, conventionsFile);
        if (fss.existsSync(convPath)) {
            try {
                const raw = await fs.readFile(convPath, "utf-8");
                const { data } = matter(raw);
                if (Array.isArray(data.conventions)) {
                    for (const c of data.conventions) {
                        conventions.push({
                            file_pattern: c.pattern || c.file_pattern || "*",
                            convention: c.convention || c.rule || String(c),
                            example: c.example,
                        });
                    }
                }
            }
            catch (e) {
                debug("惯例检测", "惯例文件解析失败 —", e);
                // 惯例文件解析失败，跳过
            }
        }
    }
    for (const filePath of filePaths) {
        try {
            const fullPath = path.resolve(projectPath, filePath);
            const stat = await fs.stat(fullPath);
            if (!stat.isFile())
                continue;
            const content = await fs.readFile(fullPath, "utf-8");
            const detected = analyzeFile(content, filePath);
            conventions.push(...detected);
        }
        catch (e) {
            debug("惯例检测", "文件分析失败 —", e);
            // 文件无法访问，跳过
        }
        if (conventions.length >= 10)
            break;
    }
    return conventions;
}
/**
 * 分析单个文件，检测其中的编码惯例。
 * @description 根据文件类型使用不同的检测策略：
 *              - Java 文件：检测缓存字段模式、事务注解用法、ServiceImpl 命名规范
 *              - TypeScript/React 文件：检测默认导出、Props interface、CSS-in-JS 方案
 * @param content - 文件内容文本
 * @param filePath - 文件路径（用于判断文件类型）
 * @returns 从该文件中检测到的惯例列表
 */
function analyzeFile(content, filePath) {
    const conventions = [];
    // 检测 Spring 惯例
    if (filePath.endsWith(".java")) {
        if (/private.*Map.*cache/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "Service 类包含缓存字段（Map 缓存），修改时遵循此模式",
            });
        }
        if (/@Transactional/.test(content) && !/readOnly\s*=\s*true/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "写操作使用 @Transactional，查询操作不加事务注解",
            });
        }
        if (/class \w+ServiceImpl/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "使用 ServiceImpl 后缀命名实现类",
            });
        }
    }
    // 检测 React/TypeScript 惯例
    if (/\.tsx?$/.test(filePath)) {
        if (/export default/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "使用 export default 导出组件",
            });
        }
        if (/interface \w+Props/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "Props 使用 interface 定义（非 type）",
            });
        }
        if (/useStyles|makeStyles|styled/.test(content)) {
            conventions.push({
                file_pattern: filePath,
                convention: "使用 CSS-in-JS 方案管理样式",
            });
        }
    }
    return conventions;
}
//# sourceMappingURL=convention_detector.js.map