import { gitShowText } from "./git-io.js";
import { resolveSnapshotContentRelativePath, resolveSnapshotMetaRelativePath } from "./layout.js";
import { readEventSegmentsJsonl, readTaskStateBranchLayout } from "./read-branch-layout.js";
import { taskVersionMapFromProjection } from "./publish-task-state-events.js";
import { projectionFromSnapshotContent, replayTailFromSnapshot } from "./snapshot-projection.js";
import { validateTaskStateGitSnapshotMeta } from "./validate-snapshot-meta.js";
import { admitTaskStateEventStream } from "../task-state-events/event-admission.js";
import { replayTaskStateEvents } from "../task-state-events/event-applier.js";
function readSnapshotContent(workspacePath, ref, snapshotId) {
    const metaText = gitShowText(workspacePath, ref, resolveSnapshotMetaRelativePath(snapshotId));
    const contentText = gitShowText(workspacePath, ref, resolveSnapshotContentRelativePath(snapshotId));
    if (!metaText || !contentText) {
        return { ok: false };
    }
    const metaParsed = validateTaskStateGitSnapshotMeta(JSON.parse(metaText));
    if (!metaParsed.ok) {
        return { ok: false };
    }
    return {
        ok: true,
        content: JSON.parse(contentText),
        throughSequence: metaParsed.data.throughSequence
    };
}
/** Admit remote JSONL events; lifecycle events require the bootstrap snapshot as replay seed. */
export function admitRemoteEventStream(workspacePath, ref, manifest, rawEvents) {
    const snapshotId = manifest.head.latestSnapshotId;
    if (!snapshotId) {
        const admitted = admitTaskStateEventStream(rawEvents);
        return admitted.ok ? admitted : { ok: false, error: admitted.error };
    }
    const snapshotRead = readSnapshotContent(workspacePath, ref, snapshotId);
    if (!snapshotRead.ok) {
        return {
            ok: false,
            error: {
                code: "schema-validation-failed",
                message: `snapshot '${snapshotId}' is missing or invalid on ${ref}`
            }
        };
    }
    const tailEvents = rawEvents.filter((event) => {
        return (event !== null &&
            typeof event === "object" &&
            !Array.isArray(event) &&
            typeof event.sequence === "number" &&
            event.sequence > snapshotRead.throughSequence);
    });
    const admitted = admitTaskStateEventStream(tailEvents, {
        initialProjection: projectionFromSnapshotContent(snapshotRead.content)
    });
    return admitted.ok ? admitted : { ok: false, error: admitted.error };
}
export function readRemoteSnapshotProjection(workspacePath, ref, tipSha) {
    const layoutRead = readTaskStateBranchLayout(workspacePath, ref, tipSha);
    if (!layoutRead.ok) {
        return null;
    }
    const segmentPaths = layoutRead.layout.eventSegmentPaths;
    const eventsRead = readEventSegmentsJsonl(workspacePath, ref, segmentPaths);
    const rawEvents = eventsRead.ok && eventsRead.lines.length > 0
        ? eventsRead.lines.map((line) => JSON.parse(line))
        : [];
    const snapshotId = layoutRead.layout.manifest.head.latestSnapshotId;
    if (!snapshotId) {
        const admitted = admitTaskStateEventStream(rawEvents);
        const events = admitted.ok ? admitted.events : [];
        if (events.length === 0) {
            return null;
        }
        const replayed = replayTaskStateEvents(events);
        return replayed.ok ? replayed.result.projection : null;
    }
    const snapshotRead = readSnapshotContent(workspacePath, ref, snapshotId);
    if (!snapshotRead.ok) {
        return null;
    }
    const admitted = admitRemoteEventStream(workspacePath, ref, layoutRead.layout.manifest, rawEvents);
    const events = admitted.ok ? admitted.events : [];
    const tailReplay = replayTailFromSnapshot({
        snapshot: snapshotRead.content,
        throughSequence: snapshotRead.throughSequence,
        tailEvents: events
    });
    return tailReplay.ok ? tailReplay.projection : null;
}
export function readRemoteTaskVersionMap(workspacePath, ref, tipSha) {
    const projection = readRemoteSnapshotProjection(workspacePath, ref, tipSha);
    if (!projection) {
        return new Map();
    }
    return taskVersionMapFromProjection(projection);
}
export function expectedVersionsForPublish(_storeVersions, remoteVersions, taskIds) {
    const out = {};
    for (const taskId of taskIds) {
        const remote = remoteVersions.get(taskId);
        out[taskId] = remote !== undefined ? remote : 0;
    }
    return out;
}
