import { debug } from "./core/logger.js";
import { isPathInScope } from "./core/path_scope_utils.js";
/**
 * 执行预测性冲突检测和跨仓库关联分析。
 * 检测维度：
 *   1. 当前分支与 main 的领先提交数
 *   2. 主分支是否超过 7 天未更新
 *   3. 本地变更文件在其他分支是否有修改（潜在冲突）
 *   4. 跨仓库 API 契约变更影响分析
 * @param input - 变更协调输入参数
 * @returns 协调检查结果，包含分支信息、冲突警告、跨仓库提示和摘要
 */
export async function checkConflicts(input) {
    debug("change_coordinator", "checkConflicts() 开始执行");
    const { projectPath, config, gitOps } = input;
    const result = {
        branch: "",
        local_changes: [],
        conflict_warnings: [],
        cross_repo_hints: [],
        commits_ahead: 0,
        stale_main_warning: false,
        summary: "",
    };
    // 1. 获取当前分支名称
    try {
        result.branch = input.branch ?? await gitOps.getCurrentBranch(projectPath);
    }
    catch {
        result.summary = "无法获取当前分支信息";
        return result;
    }
    // 2. 获取本地已变更的文件列表
    try {
        const diff = await gitOps.getDiff(projectPath);
        result.local_changes = diff.map((d) => d.file);
    }
    catch {
        /* 工作区不干净是正常情况，忽略 diff 获取失败 */
    }
    // 3. 计算当前分支相对于 main 的领先提交数
    const mainBranch = await detectMainBranch(gitOps, projectPath);
    if (mainBranch) {
        try {
            const mergeBase = await gitOps.getMergeBase(projectPath, result.branch, mainBranch);
            const log = await gitOps.getLog(projectPath, { maxCount: 50 });
            // 在提交日志中找到 merge base 的位置，其索引即为领先提交数
            const baseIdx = log.findIndex((e) => e.hash.startsWith(mergeBase.slice(0, 7)));
            result.commits_ahead = baseIdx >= 0 ? baseIdx : log.length;
            // 检测主分支是否过期（超过 7 天无新提交）
            // 待办: getLog 没有 branch/ref 参数，无法直接查询 main 的日志
            // 此处使用 path: mainBranch 作为启发式占位 — 结果可能不准确
            // 正确修复需要在 GitOperations.getLog 中添加 `ref` 选项
            const mainLog = await gitOps.getLog(projectPath, { maxCount: 1, path: mainBranch });
            if (mainLog.length > 0) {
                const lastMainCommit = new Date(mainLog[0].date);
                const daysSinceMain = (Date.now() - lastMainCommit.getTime()) / (1000 * 60 * 60 * 24);
                // 主分支超过 7 天未更新视为过期
                result.stale_main_warning = daysSinceMain > 7;
            }
        }
        catch (e) {
            debug("change_coordinator", "错误 —", e);
        }
    }
    // 4. 检查本地变更文件在其他分支中是否存在冲突风险
    try {
        const branches = await gitOps.listBranches(projectPath);
        // 过滤掉当前分支和主分支，仅检查其他功能分支
        const otherBranches = branches.filter((b) => !b.isCurrent && b.name !== mainBranch);
        // 并行检查本地变更文件在其他分支中的冲突风险（替代原 N+1 串行循环）
        const branchChecks = result.local_changes.flatMap((localFile) => otherBranches.slice(0, 10).map(async (otherBranch) => {
            try {
                // 待办: getLog 仅返回当前分支的日志（无 branch/ref 参数）
                // 此处使用基于路径的过滤，并传入本地文件路径
                // 正确修复需在 GitOperations.getLog 中添加 `ref` 选项以按分支查询
                const otherLog = await gitOps.getLog(projectPath, {
                    maxCount: 5,
                    path: localFile,
                });
                return { localFile, otherBranch, otherLog };
            }
            catch {
                return null;
            }
        }));
        const branchResults = await Promise.allSettled(branchChecks);
        for (const settled of branchResults) {
            if (settled.status !== "fulfilled" || !settled.value)
                continue;
            const { localFile, otherBranch, otherLog } = settled.value;
            if (otherLog.length > 0) {
                const existing = result.conflict_warnings.find((w) => w.file === localFile);
                if (!existing) {
                    result.conflict_warnings.push({
                        file: localFile,
                        risk: "high",
                        reason: `文件 ${localFile} 在其他分支 ${otherBranch.name} 也有修改`,
                        other_branch: otherBranch.name,
                        other_author: otherLog[0].author,
                    });
                }
            }
        }
    }
    catch {
        /* branches listing may fail */
    }
    // 5. 跨仓库协调提示（仅在多仓库配置时生效）
    if (config.repos.length > 1) {
        // 匹配 API 契约相关文件的关键词模式
        const apiPatterns = /controller|dto|request|response|api|contract|interface|types/i;
        // 两两组合检查仓库间的契约影响
        for (let i = 0; i < config.repos.length; i++) {
            for (let j = i + 1; j < config.repos.length; j++) {
                const repoAFiles = result.local_changes.filter((f) => config.repos[i].scope.some((s) => isPathInScope(f, s, { caseSensitive: true })) && apiPatterns.test(f));
                if (repoAFiles.length > 0) {
                    result.cross_repo_hints.push({
                        repo_a: config.repos[i].name,
                        repo_b: config.repos[j].name,
                        shared_contract: repoAFiles[0],
                        description: `${config.repos[i].name} 中修改了 API 契约文件 ${repoAFiles[0]}，可能影响 ${config.repos[j].name}`,
                    });
                }
            }
        }
    }
    // 6. 生成中文摘要
    const parts = [];
    if (result.conflict_warnings.length > 0) {
        parts.push(`${result.conflict_warnings.length} 个潜在冲突`);
    }
    if (result.cross_repo_hints.length > 0) {
        parts.push(`${result.cross_repo_hints.length} 个跨仓库提示`);
    }
    if (result.stale_main_warning) {
        parts.push("主分支超过 7 天未更新");
    }
    result.summary = parts.length > 0 ? parts.join("，") : "未发现冲突风险";
    return result;
}
/**
 * 自动检测主分支名称。优先选择 main，其次 master。
 * @param gitOps - Git 操作封装
 * @param cwd - 工作目录路径
 * @returns 主分支名称（默认 "main"）
 */
async function detectMainBranch(gitOps, cwd) {
    try {
        const branches = await gitOps.listBranches(cwd);
        const main = branches.find((b) => b.name === "main" || b.name === "master");
        return main?.name ?? "main";
    }
    catch {
        return "main";
    }
}
//# sourceMappingURL=change_coordinator.js.map