import { collectProjectGraphSources, diffSourceHashes, hashText, loadProjectGraphPolicy, projectGraphCachePath, projectGraphPath, readProjectGraph, readProjectGraphSourceHashes, writeProjectGraph, writeProjectGraphSourceHashes, } from './cache.js';
import { extractGitGraph, extractReleaseGraph } from './extractors/git-extractor.js';
import { extractHandoffGraph } from './extractors/handoff-extractor.js';
import { extractSpecGraph } from './extractors/spec-extractor.js';
import { extractValidationGraph } from './extractors/validation-extractor.js';
function uniqueNodes(nodes) {
    return [...new Map(nodes.map((node) => [node.id, node])).values()];
}
function uniqueEdges(edges) {
    return [...new Map(edges.map((edge) => [edge.id, edge])).values()];
}
function validateAgainstPolicy(result, policy) {
    const nodes = result.nodes.filter((node) => policy.nodeTypes.includes(node.type));
    const nodeIds = new Set(nodes.map((node) => node.id));
    const edges = result.edges.filter((edge) => nodeIds.has(edge.from) &&
        nodeIds.has(edge.to) &&
        policy.edgeTypes.includes(edge.type) &&
        policy.confidenceLabels.includes(edge.confidence) &&
        policy.classifications.includes(edge.classification));
    return { nodes, edges };
}
export async function buildProjectKnowledgeGraph(args) {
    const policy = args.policy ?? (await loadProjectGraphPolicy());
    const sources = await collectProjectGraphSources({
        projectId: args.projectId,
        projectPath: args.projectPath,
        policy,
    });
    const previousHashes = await readProjectGraphSourceHashes(args.projectId, policy);
    const diff = diffSourceHashes(sources, previousHashes);
    const existingGraph = await readProjectGraph(args.projectId, policy);
    if (existingGraph !== null && diff.changed.length === 0) {
        return {
            graph: existingGraph,
            graphPath: projectGraphPath(args.projectId, policy),
            cachePath: projectGraphCachePath(args.projectId, policy),
            reprocessedSources: [],
            skippedSources: diff.skipped,
            usedCache: true,
        };
    }
    const extracted = [];
    for (const source of sources) {
        if (source.kind === 'spec') {
            extracted.push(extractSpecGraph(source, policy));
        }
        else if (source.kind === 'validation') {
            extracted.push(extractValidationGraph(source, policy));
        }
        else if (source.kind === 'handoff') {
            extracted.push(extractHandoffGraph(source, policy));
        }
        else if (source.kind === 'release-events') {
            extracted.push(extractReleaseGraph(source, policy));
        }
    }
    extracted.push(await extractGitGraph({ projectPath: args.projectPath, policy }));
    const validated = extracted.map((result) => validateAgainstPolicy(result, policy));
    const nodes = uniqueNodes(validated.flatMap((result) => result.nodes));
    const edges = uniqueEdges(validated.flatMap((result) => result.edges));
    const sourceHashes = diff.next;
    const sourceHash = hashText(JSON.stringify(sourceHashes));
    const graph = {
        version: 1,
        graphVersion: policy.graphVersion,
        projectId: args.projectId,
        projectPath: args.projectPath,
        generatedAt: new Date().toISOString(),
        sourceHash,
        sourceHashes,
        metadata: {
            nodeCount: nodes.length,
            edgeCount: edges.length,
            sourceCount: sources.length,
            reprocessedSourceCount: diff.changed.length,
            skippedSourceCount: diff.skipped.length,
        },
        nodes,
        edges,
    };
    await writeProjectGraph(args.projectId, policy, graph);
    await writeProjectGraphSourceHashes(args.projectId, policy, sourceHashes);
    return {
        graph,
        graphPath: projectGraphPath(args.projectId, policy),
        cachePath: projectGraphCachePath(args.projectId, policy),
        reprocessedSources: diff.changed,
        skippedSources: diff.skipped,
        usedCache: false,
    };
}
//# sourceMappingURL=builder.js.map