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

import { traceDisplayRows } from "../../../../tools/src/hwlab-cli/trace-renderer";

test("web trace rows use assistant content instead of terminal/result boilerplate", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-04T08:31:11.567Z" },
    { seq: 22, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "你好，真实回复", createdAt: "2026-06-04T08:31:27.644Z" },
    { seq: 24, label: "agentrun:backend:turn/completed", status: "running", message: "turn/completed", createdAt: "2026-06-04T08:31:27.715Z" },
    { seq: 25, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "你好，真实回复", createdAt: "2026-06-04T08:31:27.721Z" },
    { seq: 27, label: "agentrun:terminal:completed", type: "result", status: "completed", terminal: true, message: "AgentRun terminal status completed", createdAt: "2026-06-04T08:31:27.736Z" },
    { seq: 31, label: "agentrun:result:completed", type: "result", status: "completed", terminal: true, message: "AgentRun result is ready for HWLAB short-connection polling.", createdAt: "2026-06-04T08:31:27.765Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-04T08:31:11.567Z" }, events);
  const terminalRows = rows.filter((row) => row.terminal === true);

  assert.equal(terminalRows.length, 1);
  assert.equal(terminalRows[0]?.body, "你好，真实回复");
  assert.doesNotMatch(rows.map((row) => row.body ?? "").join("\n"), /AgentRun terminal status completed|short-connection polling/u);
});

test("web trace rows keep every assistant message and mark only the last one terminal", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-04T12:13:58.212Z" },
    { seq: 42, label: "agentrun:assistant:message", type: "assistant", status: "running", messageIndex: 1, messageCount: 3, message: "我先读取 hwpod-cli 技能文档。", createdAt: "2026-06-04T12:14:55.199Z" },
    { seq: 43, label: "agentrun:assistant:message", type: "assistant", status: "running", messageIndex: 2, messageCount: 3, message: "`hwpod` 已就位，runtime 已锁定到 `hwlab-v02`。", createdAt: "2026-06-04T12:14:55.203Z" },
    { seq: 44, label: "agentrun:assistant:message", type: "assistant", status: "running", messageIndex: 3, messageCount: 3, message: "**可用 HWPOD 列表**\n\n- **hwpod-freq**\n- **hwpod-f103**", createdAt: "2026-06-04T12:14:55.208Z" },
    { seq: 49, label: "agentrun:backend:backend-turn-finished", status: "running", message: "backend-turn-finished", createdAt: "2026-06-04T12:14:55.231Z" },
    { seq: 50, label: "agentrun:result:completed", type: "result", status: "completed", terminal: true, message: "AgentRun result is ready for HWLAB short-connection polling.", createdAt: "2026-06-04T12:14:55.231Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-04T12:13:58.212Z" }, events);
  const assistantRows = rows.filter((row) => row.bodyFormat === "markdown");
  const terminalRows = assistantRows.filter((row) => row.terminal === true);
  const text = assistantRows.map((row) => row.body ?? "").join("\n");

  assert.equal(assistantRows.length, 3);
  assert.equal(terminalRows.length, 1);
  assert.match(text, /我先读取 hwpod-cli/u);
  assert.match(text, /runtime 已锁定到 `hwlab-v02`/u);
  assert.match(text, /hwpod-f103/u);
  assert.match(terminalRows[0]?.header ?? "", /助手消息 3\/3，轮次完成/u);
  assert.doesNotMatch(JSON.stringify(rows), /backend-turn-finished|short-connection polling/u);
});

test("web trace rows do not fold progress assistant text into the final response (#934)", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-05T13:39:36.000Z" },
    { seq: 10, label: "agentrun:assistant:message", type: "assistant", status: "running", messageIndex: 1, messageCount: 3, message: "Let me check the available HWPODs using the hwpod CLI tool.", createdAt: "2026-06-05T13:39:38.000Z" },
    { seq: 20, label: "agentrun:assistant:message", type: "assistant", status: "running", messageIndex: 2, messageCount: 3, message: "当前工作区还没有 .hwlab/hwpod-spec.yaml 文件，所以 hwpod inspect 无法获取可用 HWPOD 信息。", createdAt: "2026-06-05T13:39:40.000Z" },
    { seq: 30, label: "agentrun:assistant:message", type: "assistant", status: "completed", messageIndex: 3, messageCount: 3, replyAuthority: true, final: true, terminal: true, message: "当前工作区没有 .hwlab/hwpod-spec.yaml，也没有 .hwlab 目录或现成的 hwpod-spec 文件。\n\n目前可用的 HWPOD：0 个。", createdAt: "2026-06-05T13:39:44.000Z" },
    { seq: 34, label: "agentrun:result:completed", type: "result", status: "completed", terminal: true, message: "AgentRun result is ready for HWLAB short-connection polling.", createdAt: "2026-06-05T13:39:44.280Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-05T13:39:36.000Z" }, events);
  const assistantRows = rows.filter((row) => row.bodyFormat === "markdown");
  const terminalRows = assistantRows.filter((row) => row.terminal === true);

  assert.equal(assistantRows.length, 3);
  assert.equal(terminalRows.length, 1);
  assert.match(assistantRows[0]?.body ?? "", /Let me check/u);
  assert.match(assistantRows[1]?.body ?? "", /当前工作区还没有/u);
  assert.match(terminalRows[0]?.body ?? "", /目前可用的 HWPOD：0 个/u);
  assert.doesNotMatch(terminalRows[0]?.body ?? "", /Let me check|当前工作区还没有/u);
});

test("web trace rows keep clean AgentRun final response when same itemId snapshots stay running (#955)", () => {
  const progressOne = "好，我来走 HWPOD 编译路径。先看看 hwpod 命令是否可用，并读取 hwpod-cli 技能了解完整的编译流程。";
  const progressTwo = "好，现在用 hwpod build 走编译。根据 skill，标准路径是 hwpod build 触发 hwpod-compiler-cli，再通过 API 发给 hwpod-node。";
  const finalText = "编译成功！来总结一下结果：\n\n hwpod build ✅ completed\n\n- 设备: D601-F103-V2 (STM32F103)\n- 工具链: Keil MDK，通过 keil-cli.py build 异步发起\n- 构建命令: py -3 keil-cli.py build -p atk_f103.uvprojx -t USART\n- exit code: 0，任务已入队列\n- 预期产物: F:\\Work\\D601-HWLAB\\projects\\01_baseline\\Output\\atk_f103.hex\n- 无 blocker";
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-06T01:46:11.000Z" },
    { seq: 17, source: "agentrun", sourceSeq: 48, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_item_0", message: progressOne, createdAt: "2026-06-06T01:46:15.000Z" },
    { seq: 22, source: "agentrun", sourceSeq: 53, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_item_0", message: progressTwo, createdAt: "2026-06-06T01:46:18.000Z" },
    { seq: 26, source: "agentrun", sourceSeq: 57, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_item_0", message: `${progressOne}${progressTwo}${finalText.slice(0, 170)}`, createdAt: "2026-06-06T01:46:24.000Z" },
    { seq: 27, source: "agentrun", sourceSeq: 58, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_item_0", message: finalText, createdAt: "2026-06-06T01:46:25.000Z" },
    { seq: 30, source: "agentrun", sourceSeq: 61, label: "agentrun:assistant:message", type: "assistant", status: "running", itemId: "msg_item_0", message: `${progressOne}${progressTwo}${finalText}`, createdAt: "2026-06-06T01:46:26.000Z" },
    { seq: 36, label: "agentrun:result:completed", type: "result", status: "completed", terminal: true, message: "AgentRun result is ready for HWLAB short-connection polling.", createdAt: "2026-06-06T01:46:28.000Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-06T01:46:11.000Z", finalResponse: { text: finalText } }, events);
  const assistantRows = rows.filter((row) => row.bodyFormat === "markdown");
  const terminalRows = assistantRows.filter((row) => row.terminal === true);

  assert.equal(terminalRows.length, 1);
  assert.equal(terminalRows[0]?.body, finalText);
  assert.doesNotMatch(terminalRows[0]?.body ?? "", /好，我来走 HWPOD 编译路径|好，现在用 hwpod build/u);
  assert.equal(assistantRows.filter((row) => /好，我来走 HWPOD 编译路径/u.test(row.body ?? "")).length, 1);
  assert.equal(assistantRows.filter((row) => /好，现在用 hwpod build/u.test(row.body ?? "")).length, 1);
});

test("web trace rows collapse tool start/completed and clean shell command escaping", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-04T12:13:58.212Z" },
    { seq: 2, label: "agentrun:tool:item/started", type: "tool_call", toolName: "commandExecution", status: "started", itemId: "call_build", command: "/bin/sh -lc \"hwpod build --target Debug --reason \\\"agent 主动 build 复测\\\"\"", createdAt: "2026-06-04T12:14:00.000Z" },
    { seq: 3, label: "agentrun:tool:item/completed", type: "tool_call", toolName: "commandExecution", status: "completed", itemId: "call_build", command: "/bin/sh -lc \"hwpod build --target Debug --reason \\\"agent 主动 build 复测\\\"\"", stdoutSummary: "{\"ok\":true,\"action\":\"hwpod-cli.invoke\",\"status\":\"completed\"}", exitCode: 0, createdAt: "2026-06-04T12:14:01.000Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-04T12:13:58.212Z" }, events);
  const toolRows = rows.filter((row) => row.rowId.startsWith("tool:"));
  const body = toolRows.map((row) => row.body ?? "").join("\n");
  const text = JSON.stringify(toolRows);

  assert.equal(toolRows.length, 1);
  assert.match(body, /hwpod build --target Debug --reason "agent 主动 build 复测"/u);
  assert.match(body, /hwpod-cli\.invoke/u);
  assert.doesNotMatch(body, /\/bin\/sh -lc|\\"/u);
  assert.match(body, /stdout:/u);
  assert.match(body, /exitCode=0/u);
  assert.doesNotMatch(text, /agentrun:tool:item\/started/u);
});

test("web trace rows dedupe AgentRun replayed source events and keep one tool row", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-04T13:40:28.612Z" },
    { seq: 9, label: "agentrun:backend:run-claimed", type: "backend", status: "running", source: "agentrun", sourceSeq: 4, message: "run-claimed", createdAt: "2026-06-04T13:40:34.601Z" },
    { seq: 22, label: "agentrun:assistant:message", type: "assistant", status: "running", source: "agentrun", sourceSeq: 17, message: "我先确认 `hwpod` 可用。", createdAt: "2026-06-04T13:40:43.286Z" },
    { seq: 23, label: "item/commandExecution:started", type: "tool_call", toolName: "commandExecution", status: "started", source: "agentrun", sourceSeq: 18, itemId: "call_function_gsuuqbm1yp0s_1", command: "/bin/sh -lc 'command -v hwpod && hwpod inspect --dry-run'", createdAt: "2026-06-04T13:40:43.458Z" },
    { seq: 24, label: "agentrun:output:stdout", type: "output", status: "running", source: "agentrun", sourceSeq: 19, message: "raw stdout should stay inside the completed tool row", createdAt: "2026-06-04T13:40:44.852Z" },
    { seq: 25, label: "item/commandExecution:completed", type: "tool_call", toolName: "commandExecution", status: "completed", source: "agentrun", sourceSeq: 20, itemId: "call_function_gsuuqbm1yp0s_1", command: "/bin/sh -lc 'command -v hwpod && hwpod inspect --dry-run'", stdoutSummary: '{"ok":true,"action":"hwpod-cli.plan"}', exitCode: 0, createdAt: "2026-06-04T13:40:44.972Z" },
    { seq: 29, label: "agentrun:backend:run-claimed", type: "backend", status: "running", source: "agentrun", sourceSeq: 4, message: "run-claimed", createdAt: "2026-06-04T13:40:34.601Z" },
    { seq: 42, label: "agentrun:assistant:message", type: "assistant", status: "running", source: "agentrun", sourceSeq: 17, message: "我先确认 `hwpod` 可用。", createdAt: "2026-06-04T13:40:43.286Z" },
    { seq: 43, label: "item/commandExecution:started", type: "tool_call", toolName: "commandExecution", status: "started", source: "agentrun", sourceSeq: 18, itemId: "call_function_gsuuqbm1yp0s_1", command: "/bin/sh -lc 'command -v hwpod && hwpod inspect --dry-run'", createdAt: "2026-06-04T13:40:43.458Z" },
    { seq: 44, label: "agentrun:output:stdout", type: "output", status: "running", source: "agentrun", sourceSeq: 19, message: "raw stdout should stay inside the completed tool row", createdAt: "2026-06-04T13:40:44.852Z" },
    { seq: 45, label: "item/commandExecution:completed", type: "tool_call", toolName: "commandExecution", status: "completed", source: "agentrun", sourceSeq: 20, itemId: "call_function_gsuuqbm1yp0s_1", command: "/bin/sh -lc 'command -v hwpod && hwpod inspect --dry-run'", stdoutSummary: '{"ok":true,"action":"hwpod-cli.plan"}', exitCode: 0, createdAt: "2026-06-04T13:40:44.972Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-04T13:40:28.612Z" }, events);
  const text = JSON.stringify(rows);
  const toolRows = rows.filter((row) => row.rowId === "tool:call_function_gsuuqbm1yp0s_1");
  const assistantRows = rows.filter((row) => row.bodyFormat === "markdown");

  assert.equal(toolRows.length, 1);
  assert.equal(assistantRows.length, 1);
  assert.equal(rows.filter((row) => /run-claimed/u.test(row.body ?? "")).length, 1);
  assert.match(toolRows[0]?.body ?? "", /command -v hwpod && hwpod inspect --dry-run/u);
  assert.match(toolRows[0]?.body ?? "", /hwpod-cli\.plan/u);
  assert.doesNotMatch(toolRows[0]?.body ?? "", /\/bin\/sh -lc/u);
  assert.doesNotMatch(text, /agentrun:output:stdout|raw stdout should stay inside/u);
});

test("web trace rows collapse duplicate assistant snapshots while preserving distinct messages", () => {
  const events: Record<string, unknown>[] = [
    { seq: 1, label: "agentrun:request:accepted", status: "accepted", createdAt: "2026-06-04T13:56:01.440Z" },
    { seq: 22, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "我先确认 `hwpod` 在 PATH 中可用，再执行 `hwpod inspect --dry-run`。", createdAt: "2026-06-04T13:56:15.000Z" },
    { seq: 24, label: "item/commandExecution:completed", type: "tool_call", toolName: "commandExecution", status: "completed", itemId: "call_profile", command: "/bin/sh -lc 'hwpod inspect --dry-run'", stdoutSummary: '{"ok":true,"action":"hwpod-cli.plan"}', exitCode: 0, createdAt: "2026-06-04T13:56:20.000Z" },
    { seq: 34, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "ISSUE857_FINAL_MARKDOWN_OK\n\n| 检查项 | 结果 | 证据 |\n| --- | --- | --- |\n| CLI 可达 | PASS | `hwpod inspect --dry-run` |", createdAt: "2026-06-04T13:56:31.000Z" },
    { seq: 35, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "ISSUE857_FINAL_MARKDOWN_OK\n\n| 检查项 | 结果 | 证据 |\n| --- | --- | --- |\n| CLI 可达 | PASS | `hwpod inspect --dry-run` |\n\n- 已执行唯一真实工具命令。\n- 未触碰写路径。", createdAt: "2026-06-04T13:56:33.000Z" },
    { seq: 38, label: "agentrun:assistant:message", type: "assistant", status: "running", message: "我先确认 `hwpod` 在 PATH 中可用，再执行 `hwpod inspect --dry-run`。", createdAt: "2026-06-04T13:56:33.100Z" },
    { seq: 39, label: "agentrun:assistant:message", type: "assistant", status: "completed", final: true, terminal: true, replyAuthority: true, message: "ISSUE857_FINAL_MARKDOWN_OK\n\n| 检查项 | 结果 | 证据 |\n| --- | --- | --- |\n| CLI 可达 | PASS | `hwpod inspect --dry-run` |\n\n- 已执行唯一真实工具命令。\n- 未触碰写路径。", createdAt: "2026-06-04T13:56:33.200Z" },
    { seq: 40, label: "agentrun:result:completed", type: "result", status: "completed", terminal: true, message: "AgentRun result is ready for HWLAB short-connection polling.", createdAt: "2026-06-04T13:56:33.300Z" }
  ];

  const rows = traceDisplayRows({ startedAt: "2026-06-04T13:56:01.440Z" }, events);
  const assistantRows = rows.filter((row) => row.bodyFormat === "markdown");
  const finalRows = assistantRows.filter((row) => /ISSUE857_FINAL_MARKDOWN_OK/u.test(row.body ?? ""));
  const progressRows = assistantRows.filter((row) => /我先确认 `hwpod`/u.test(row.body ?? ""));
  const toolRows = rows.filter((row) => row.rowId === "tool:call_profile");

  assert.equal(toolRows.length, 1);
  assert.equal(progressRows.length, 1);
  assert.equal(finalRows.length, 1);
  assert.equal(finalRows[0]?.terminal, true);
  assert.match(finalRows[0]?.body ?? "", /未触碰写路径/u);
  assert.doesNotMatch(JSON.stringify(rows), /short-connection polling/u);
});
