import { EXIT_CODES, parseCommandArgs } from "../infrastructure.js";
import { openGraph, applyCursorCeiling, emitCursorWarning } from "../shared.js";
import { historySchema } from "../schemas.js";
const HISTORY_OPTIONS = {
    node: { type: 'string' },
};
function opNodeMatches(op, nodeId) {
    return 'node' in op && op.node === nodeId;
}
function opFromMatches(op, nodeId) {
    return 'from' in op && op.from === nodeId;
}
function opToMatches(op, nodeId) {
    return 'to' in op && op.to === nodeId;
}
function opTouchesNode(op, nodeId) {
    return opNodeMatches(op, nodeId) || opFromMatches(op, nodeId) || opToMatches(op, nodeId);
}
function patchTouchesNode(entry, nodeId) {
    if (nodeId === null) {
        return true;
    }
    return entry.patch.ops.some((op) => opTouchesNode(op, nodeId));
}
function toHistoryEntry(entry, writer) {
    return {
        sha: entry.sha.slice(0, 7),
        fullSha: entry.sha,
        writer,
        lamport: entry.patch.lamport,
        opCount: entry.patch.ops.length,
    };
}
/** Handles `git warp history`: lists a writer's patch chain. */
export default async function handleHistory({ options, args }) {
    const { values } = parseCommandArgs(args, HISTORY_OPTIONS, historySchema);
    const { graph, graphName, persistence } = await openGraph(options);
    const cursorInfo = await applyCursorCeiling(graph, persistence, graphName);
    emitCursorWarning(cursorInfo, null);
    const node = values.node ?? null;
    const patches = await graph.getWriterPatches(options.writer);
    const entries = patches
        .filter((entry) => patchTouchesNode(entry, node))
        .sort((a, b) => a.patch.lamport - b.patch.lamport)
        .map((entry) => toHistoryEntry(entry, options.writer));
    return {
        payload: { graph: graphName, writer: options.writer, node, entries },
        exitCode: EXIT_CODES.OK,
    };
}
