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

import type { ChatMessage } from "@/types";
import { applyWorkbenchIsolatedKafkaDebugEvent, createWorkbenchIsolatedKafkaDebugState, workbenchCurrentDebugTraceId } from "./workbench-isolated-kafka-debug";

test("isolated Kafka debug projects assistant and terminal events through production reducers", () => {
  const traceId = "trc_isolated_reducer";
  const assistant = debugEnvelope("41", {
    schema: "hwlab.event.debug.v1",
    eventId: "hwevt_assistant",
    eventType: "assistant",
    traceId,
    hwlabSessionId: "ses_isolated_reducer",
    event: {
      sourceEventId: "agevt_assistant",
      projectedSeq: 1,
      traceId,
      sessionId: "ses_isolated_reducer",
      type: "assistant",
      eventType: "assistant",
      status: "running",
      assistantText: "isolated partial response",
      createdAt: "2026-07-10T10:00:01.000Z"
    }
  });
  const terminal = debugEnvelope("42", {
    schema: "hwlab.event.debug.v1",
    eventId: "hwevt_terminal",
    eventType: "terminal",
    traceId,
    hwlabSessionId: "ses_isolated_reducer",
    event: {
      sourceEventId: "agevt_terminal",
      projectedSeq: 2,
      traceId,
      sessionId: "ses_isolated_reducer",
      type: "result",
      eventType: "terminal",
      terminal: true,
      status: "completed",
      createdAt: "2026-07-10T10:00:02.000Z",
      elapsedMs: 1000
    }
  });

  const running = applyWorkbenchIsolatedKafkaDebugEvent(createWorkbenchIsolatedKafkaDebugState(), assistant, traceId);
  assert.equal(running.appliedCount, 1);
  assert.equal(running.message?.status, "running");
  assert.equal(running.message?.text, "isolated partial response");
  assert.equal(running.message?.runnerTrace?.eventSource, "hwlab-kafka-sse");
  assert.equal(running.message?.runnerTrace?.eventCount, 1);

  const completed = applyWorkbenchIsolatedKafkaDebugEvent(running, terminal, traceId);
  assert.equal(completed.receivedCount, 2);
  assert.equal(completed.appliedCount, 2);
  assert.equal(completed.lastOffset, "42");
  assert.equal(completed.message?.status, "completed");
  assert.equal(completed.message?.text, "isolated partial response");
  assert.equal(completed.message?.traceAutoLifecycle, "terminal");
  const finalResponse = completed.message?.finalResponse as { text?: string } | null | undefined;
  assert.equal(finalResponse?.text, "isolated partial response");
  assert.equal(completed.message?.runnerTrace?.eventCount, 2);
  assert.deepEqual(completed.message?.runnerTrace?.events?.map((event) => event.sourceEventId), ["agevt_assistant", "agevt_terminal"]);
  assert.equal(completed.logs.every((entry) => entry.accepted), true);
});

test("isolated Kafka debug rejects another trace without touching a canonical message", () => {
  const canonical: ChatMessage = Object.freeze({
    id: "msg_product",
    role: "agent",
    title: "Code Agent",
    text: "product state",
    status: "running",
    traceId: "trc_product",
    createdAt: "2026-07-10T10:00:00.000Z"
  }) as ChatMessage;
  const state = applyWorkbenchIsolatedKafkaDebugEvent(createWorkbenchIsolatedKafkaDebugState(), debugEnvelope("51", {
    schema: "hwlab.event.debug.v1",
    eventType: "assistant",
    traceId: "trc_other",
    event: { traceId: "trc_other", type: "assistant", text: "must stay isolated" }
  }), "trc_expected");

  assert.equal(state.message, null);
  assert.equal(state.receivedCount, 1);
  assert.equal(state.appliedCount, 0);
  assert.equal(state.error, "debug-envelope-trace-mismatch");
  assert.equal(canonical.text, "product state");
});

test("current Workbench debug trace prefers the active agent turn", () => {
  const messages = [
    { id: "msg_old", role: "agent", title: "Code Agent", text: "done", status: "completed", traceId: "trc_old", createdAt: "2026-07-10T10:00:00.000Z" },
    { id: "msg_current", role: "agent", title: "Code Agent", text: "", status: "running", traceId: "trc_current", createdAt: "2026-07-10T10:01:00.000Z" }
  ] as ChatMessage[];
  assert.equal(workbenchCurrentDebugTraceId(messages, "trc_session_fallback"), "trc_current");
  assert.equal(workbenchCurrentDebugTraceId([], "trc_session_fallback"), "trc_session_fallback");
});

function debugEnvelope(offset: string, value: Record<string, unknown>) {
  return {
    ok: true,
    stream: "hwlab-debug" as const,
    topic: "hwlab.event.debug.v1",
    partition: 0,
    offset,
    value,
    valuesPrinted: false
  };
}
