import { describe, expect, it } from "bun:test";

import {
  appendBackendToolArtifact,
  cancelBackendTodos,
  upsertBackendQuestion,
} from "../../src/routes/chatUiState.js";

describe("appendBackendToolArtifact", () => {
  it("persists show_chart tool calls as chart artifacts", () => {
    const artifacts = appendBackendToolArtifact([], {
      session_id: "session-1",
      tool: "show_chart",
      reason: "测试折线图渲染",
      params: {
        title: "压力曲线",
        chart_type: "line",
        x_data: ["00:00", "01:00"],
        series: [{ name: "P-101", data: [0.42, 0.41] }],
      },
    }) as Array<Record<string, unknown>>;

    expect(artifacts).toHaveLength(1);
    expect(artifacts[0]).toMatchObject({
      tool: "show_chart",
      kind: "chart",
      title: "压力曲线",
      description: "测试折线图渲染",
      params: {
        chart_type: "line",
        x_data: ["00:00", "01:00"],
        series: [{ name: "P-101", data: [0.42, 0.41] }],
      },
    });
    expect(artifacts[0]).toEqual(
      expect.objectContaining({
        id: expect.stringMatching(/^show_chart-/),
      }),
    );
  });
});

describe("upsertBackendQuestion", () => {
  it("replaces a tool-call placeholder with the actionable question request", () => {
    const questions = upsertBackendQuestion(
      [
        {
          requestId: "call-1",
          sessionId: "session-1",
          questions: [
            {
              header: "测试问题",
              question: "你觉得这个 question 工具好用吗？",
              options: [{ label: "非常好用", description: "交互清晰，选项方便" }],
            },
          ],
          tool: { messageID: "message-1", callID: "call-1" },
          createdAt: 123,
          status: "pending",
        },
      ],
      {
        session_id: "session-1",
        request_id: "question-1",
        questions: [
          {
            header: "测试问题",
            question: "你觉得这个 question 工具好用吗？",
            options: [{ label: "非常好用", description: "交互清晰，选项方便" }],
          },
        ],
        tool: { messageID: "message-1", callID: "call-1" },
        created_at: 456,
      },
    );

    expect(questions).toHaveLength(1);
    expect(questions[0]).toMatchObject({
      requestId: "question-1",
      tool: { callID: "call-1" },
      status: "pending",
    });
  });

  it("does not replace an actionable question request with a later tool-call placeholder", () => {
    const questions = upsertBackendQuestion(
      [
        {
          requestId: "question-1",
          sessionId: "session-1",
          questions: [
            {
              header: "测试问题",
              question: "你觉得这个 question 工具好用吗？",
              options: [{ label: "非常好用", description: "交互清晰，选项方便" }],
            },
          ],
          tool: { messageID: "message-1", callID: "call-1" },
          createdAt: 123,
          status: "pending",
        },
      ],
      {
        session_id: "session-1",
        request_id: "call-1",
        questions: [
          {
            header: "测试问题",
            question: "你觉得这个 question 工具好用吗？",
            options: [{ label: "非常好用", description: "交互清晰，选项方便" }],
          },
        ],
        tool: { messageID: "message-1", callID: "call-1" },
        created_at: 456,
      },
    );

    expect(questions).toHaveLength(1);
    expect(questions[0]).toMatchObject({
      requestId: "question-1",
      tool: { callID: "call-1" },
      status: "pending",
    });
  });
});

describe("cancelBackendTodos", () => {
  it("marks pending and in-progress todos as cancelled", () => {
    const cancelled = cancelBackendTodos([
      {
        sessionId: "session-1",
        todos: [
          { id: "todo-1", content: "分析水位", status: "in_progress" },
          { id: "todo-2", content: "生成建议", status: "pending" },
          { id: "todo-3", content: "完成报告", status: "completed" },
        ],
        createdAt: 123,
      },
    ]);

    expect(cancelled).toEqual([
      expect.objectContaining({
        todos: [
          expect.objectContaining({
            id: "todo-1",
            status: "cancelled",
            updatedAt: expect.any(Number),
          }),
          expect.objectContaining({
            id: "todo-2",
            status: "cancelled",
            updatedAt: expect.any(Number),
          }),
          expect.objectContaining({
            id: "todo-3",
            status: "completed",
          }),
        ],
      }),
    ]);
  });
});
