import { debug } from "../engine/core/logger.js";
import { safeMatchIndex } from "../engine/core/helpers.js";
const SEMANTIC_CONFLICT_RULES = [
    {
        group: "api_response_format",
        topic_patterns: [/api|接口|响应|response/i],
        values: [
            { value: "ApiResponse", positive_patterns: [/统一(?:响应|返回)[^。\n]{0,24}\bApiResponse\b/i, /(?:必须|统一|采用|使用|标准为)[^。\n]{0,16}\bApiResponse\b/i] },
            { value: "Result", positive_patterns: [/统一(?:响应|返回)[^。\n]{0,24}\bResult\b/i, /(?:必须|统一|采用|使用|标准为)[^。\n]{0,16}\bResult\b/i] },
            { value: "ResponseEntity", positive_patterns: [/统一(?:响应|返回)[^。\n]{0,24}\bResponseEntity\b/i, /(?:必须|统一|采用|使用|标准为)[^。\n]{0,16}\bResponseEntity\b/i] },
        ],
    },
    {
        group: "pagination_format",
        topic_patterns: [/分页|pagination|page/i],
        values: [
            { value: "page_size", positive_patterns: [/分页(?:参数|请求|接口)[^。\n]{0,32}(?:统一|采用|使用|标准为)[^。\n]{0,24}(?:pageSize|page_size|page\/size|page\s*\+\s*size)/i] },
            { value: "limit_offset", positive_patterns: [/分页(?:参数|请求|接口)[^。\n]{0,32}(?:统一|采用|使用|标准为)[^。\n]{0,24}(?:limit\/offset|limit\s*\+\s*offset)/i] },
        ],
    },
    {
        group: "logging_correlation_field",
        topic_patterns: [/日志|log|trace|request/i],
        values: [
            { value: "trace_id", positive_patterns: [/(?:日志|链路|请求)(?:字段|ID)?[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:traceId|trace_id)/i] },
            { value: "request_id", positive_patterns: [/(?:日志|链路|请求)(?:字段|ID)?[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:requestId|request_id)/i] },
        ],
    },
    {
        group: "database_naming",
        topic_patterns: [/数据库|表名|字段|database|table|column/i],
        values: [
            { value: "snake_case", positive_patterns: [/(?:数据库|表名|字段|table|column)[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:snake_case|下划线)/i] },
            { value: "camelCase", positive_patterns: [/(?:数据库|表名|字段|table|column)[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:camelCase|驼峰)/i] },
        ],
    },
    {
        group: "permission_model",
        topic_patterns: [/权限|permission|auth|租户/i],
        values: [
            { value: "rbac", positive_patterns: [/(?:权限|授权|permission|auth)[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:RBAC|角色)/i] },
            { value: "abac", positive_patterns: [/(?:权限|授权|permission|auth)[^。\n]{0,24}(?:统一|采用|使用|标准为)[^。\n]{0,16}(?:ABAC|属性)/i] },
        ],
    },
];
function inferSemanticDecision(entry) {
    const topicText = `${entry.name} ${entry.type} ${entry.when} ${entry.scope.join(" ")} ${entry.products.join(" ")} ${entry.tech_stack ?? ""}`;
    const bodyText = `${topicText} ${entry.body ?? ""}`;
    for (const rule of SEMANTIC_CONFLICT_RULES) {
        if (!rule.topic_patterns.some((pattern) => pattern.test(topicText) || pattern.test(bodyText)))
            continue;
        const matched = rule.values.find((candidate) => {
            for (const pattern of candidate.positive_patterns) {
                for (const match of bodyText.matchAll(new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`))) {
                    const context = bodyText.slice(Math.max(0, safeMatchIndex(match) - 16), Math.min(bodyText.length, safeMatchIndex(match) + match[0].length + 16));
                    if (/例如|如\s|比如|示例|不得|不要|禁止|不应|不能|避免/.test(context))
                        continue;
                    return true;
                }
            }
            return false;
        });
        if (matched)
            return { group: rule.group, value: matched.value };
    }
    return null;
}
/**
 * 检测知识条目之间的冲突。
 * @description 先保留旧的 type:when 重复检查，再按语义主题检测同一规则域中的互斥取值。
 * @param entries - 待检测的知识条目列表
 * @returns 包含冲突信息的数组，每项包含冲突的条目和冲突类型
 */
export function detectConflicts(entries) {
    debug("冲突检测", "开始检测 — 条目数: " + entries.length);
    const issues = [];
    const activeEntries = entries.filter((e) => e.status === "active");
    const whenMap = new Map();
    for (const e of activeEntries) {
        const key = `${e.type}:${e.when}`;
        if (!whenMap.has(key))
            whenMap.set(key, []);
        whenMap.get(key).push(e);
    }
    for (const [, grouped] of whenMap) {
        if (grouped.length > 1) {
            for (const e of grouped) {
                issues.push({ entry: e, issue: "conflict" });
            }
        }
    }
    const semanticMap = new Map();
    for (const entry of activeEntries) {
        const decision = inferSemanticDecision(entry);
        if (!decision)
            continue;
        const grouped = semanticMap.get(decision.group) ?? [];
        grouped.push({ entry, value: decision.value });
        semanticMap.set(decision.group, grouped);
    }
    for (const [group, grouped] of semanticMap) {
        const values = new Set(grouped.map((item) => item.value));
        if (values.size <= 1)
            continue;
        for (const item of grouped) {
            issues.push({
                entry: item.entry,
                issue: `semantic_conflict:${group}:${Array.from(values).join("/")}`,
            });
        }
    }
    return issues;
}
/**
 * 检测元数据冲突 — scope 交叉但 products 互斥的条目对。
 * @description 遍历所有活跃条目，检查是否存在两个条目：
 *              1. scope 有交集（任一条目的 scope 包含另一条的任意 scope 值）
 *              2. products 互斥（双方 products 列表无交集且均非 "*"）
 *              此类组合意味着：在交集 scope 下，不同产品会获得矛盾的知识指导。
 * @param entries - 待检测的知识条目列表
 * @returns 包含元数据冲突信息的数组
 */
export function detectMetadataConflicts(entries) {
    debug("元数据冲突检测", "开始检测 — 条目数: " + entries.length);
    const issues = [];
    const activeEntries = entries.filter((e) => e.status === "active");
    for (let i = 0; i < activeEntries.length; i++) {
        for (let j = i + 1; j < activeEntries.length; j++) {
            const a = activeEntries[i];
            const b = activeEntries[j];
            // 跳过同一条目（ID 相同视为同一条目）
            if (a.id === b.id)
                continue;
            // 检查 scope 交叉
            const aScopeSet = new Set(a.scope.map((s) => s.toLowerCase()));
            const bScopeSet = new Set(b.scope.map((s) => s.toLowerCase()));
            let scopeOverlap = false;
            for (const s of aScopeSet) {
                if (bScopeSet.has(s) || s === "shared" || s === "*") {
                    scopeOverlap = true;
                    break;
                }
            }
            if (!scopeOverlap)
                continue;
            // 检查 products 互斥（无交集且均非 "*"）
            const aProductsSet = new Set(a.products.map((p) => p.toLowerCase()));
            const bProductsSet = new Set(b.products.map((p) => p.toLowerCase()));
            // 任一为 "*" 表示适用于所有产品，不算互斥
            if (aProductsSet.has("*") || bProductsSet.has("*"))
                continue;
            // 存在交集则不互斥
            let hasProductIntersection = false;
            for (const p of aProductsSet) {
                if (bProductsSet.has(p)) {
                    hasProductIntersection = true;
                    break;
                }
            }
            if (hasProductIntersection)
                continue;
            // scope 交叉且 products 互斥 → 元数据冲突
            const overlapScopes = [...aScopeSet].filter((s) => bScopeSet.has(s) || s === "shared" || s === "*");
            issues.push({
                entry: a,
                conflicting_entry: b,
                issue: `metadata_conflict:scope_overlap=[${overlapScopes.join(",")}]:products_disjoint`,
            });
            issues.push({
                entry: b,
                conflicting_entry: a,
                issue: `metadata_conflict:scope_overlap=[${overlapScopes.join(",")}]:products_disjoint`,
            });
        }
    }
    if (issues.length > 0) {
        debug("元数据冲突检测", `发现 ${issues.length / 2} 对元数据冲突。`);
    }
    return issues;
}
//# sourceMappingURL=conflict_detector.js.map