import assert from "node:assert/strict";
import { test } from "bun:test";

import type { ChatMessage, TraceEvent } from "@/types";
import { mergeRunnerTrace } from "./workbench-trace-snapshot";

function event(projectedSeq: number, label = `event-${projectedSeq}`): TraceEvent {
  return { projectedSeq, label, type: "event" };
}

function trace(input: NonNullable<ChatMessage["runnerTrace"]>): NonNullable<ChatMessage["runnerTrace"]> {
  return input;
}

test("mergeRunnerTrace preserves event identity for replayed trace-api range", () => {
  const previousEvents = [event(1), event(2)];
  const previous = trace({ traceId: "trc_replay", eventSource: "trace-api", events: previousEvents, nextProjectedSeq: 2, range: { toProjectedSeq: 2 }, hasMore: true });
  const next = trace({ traceId: "trc_replay", eventSource: "trace-api", events: [event(2)], range: { afterProjectedSeq: 1, fromProjectedSeq: 2, toProjectedSeq: 2, returned: 1 }, hasMore: true });

  const merged = mergeRunnerTrace(previous, next);

  assert.equal(merged.events, previousEvents);
  assert.equal(merged.events?.length, 2);
});

test("mergeRunnerTrace appends only delta events after the canonical cursor", () => {
  const previousEvents = [event(1), event(2)];
  const delta = [event(3), event(4)];
  const previous = trace({ traceId: "trc_delta", eventSource: "trace-api", events: previousEvents, nextProjectedSeq: 2, range: { toProjectedSeq: 2 }, hasMore: true });
  const next = trace({ traceId: "trc_delta", eventSource: "trace-api", events: delta, range: { afterProjectedSeq: 2, fromProjectedSeq: 3, toProjectedSeq: 4, returned: 2 }, hasMore: false, fullTraceLoaded: true });

  const merged = mergeRunnerTrace(previous, next);

  assert.notEqual(merged.events, previousEvents);
  assert.deepEqual(merged.events?.map((item) => item.projectedSeq), [1, 2, 3, 4]);
  assert.equal(merged.events?.[0], previousEvents[0]);
  assert.equal(merged.events?.[2], delta[0]);
});

test("mergeRunnerTrace can seal terminal metadata without requiring trace rows", () => {
  const previousEvents = [event(1), event(2)];
  const previous = trace({ traceId: "trc_terminal", eventSource: "trace-api", events: previousEvents, nextProjectedSeq: 2, range: { toProjectedSeq: 2 }, hasMore: true, status: "running" });
  const terminal = trace({ traceId: "trc_terminal", eventSource: "turn-authority", events: [], status: "completed", traceStatus: "completed", fullTraceLoaded: false });

  const merged = mergeRunnerTrace(previous, terminal);

  assert.equal(merged.status, "completed");
  assert.equal(merged.events, previousEvents);
});

test("mergeRunnerTrace accumulates live Kafka deltas with an honest source and event count", () => {
  const previous = trace({
    eventSource: "hwlab-kafka-sse",
    eventCount: 1,
    events: [{ source: "agentrun.kafka", sourceSeq: 1, type: "assistant", label: "assistant" }]
  });
  const next = trace({
    eventSource: "hwlab-kafka-sse",
    eventCount: 1,
    events: [{ source: "agentrun.kafka", sourceSeq: 2, type: "tool", label: "tool" }]
  });

  const merged = mergeRunnerTrace(previous, next);

  assert.equal(merged.eventSource, "hwlab-kafka-sse");
  assert.equal(merged.eventCount, 2);
  assert.deepEqual(merged.events?.map((event) => event.sourceSeq), [1, 2]);
});

test("mergeRunnerTrace deduplicates live Kafka by sourceEventId and retains terminal events", () => {
  const previous = trace({
    traceId: "trc_live_identity",
    eventSource: "hwlab-kafka-sse",
    status: "running",
    eventCount: 1,
    events: [{ sourceEventId: "evt_assistant", runId: "run_live_identity", sourceSeq: 1, type: "assistant", message: "answer" }]
  });
  const duplicate = trace({
    traceId: "trc_live_identity",
    eventSource: "hwlab-kafka-sse",
    status: "running",
    eventCount: 1,
    events: [{ sourceEventId: "evt_assistant", runId: "run_live_identity", sourceSeq: 99, type: "assistant", message: "duplicate" }]
  });
  const deduplicated = mergeRunnerTrace(previous, duplicate);
  const terminal = mergeRunnerTrace(deduplicated, trace({
    traceId: "trc_live_identity",
    eventSource: "hwlab-kafka-sse",
    status: "completed",
    eventCount: 1,
    events: [{ sourceEventId: "evt_terminal", runId: "run_live_identity", sourceSeq: 2, type: "result", terminal: true, status: "completed" }]
  }));

  assert.equal(deduplicated.eventCount, 1);
  assert.equal(deduplicated.events?.[0]?.message, "answer");
  assert.equal(terminal.status, "completed");
  assert.equal(terminal.eventCount, 2);
  assert.deepEqual(terminal.events?.map((event) => event.sourceEventId), ["evt_assistant", "evt_terminal"]);
});
