import { afterEach, describe, expect, it, vi } from "vitest";
import { createAgentApiClient } from "./client";

describe("Agent API client sessions", () => {
  afterEach(() => {
    vi.unstubAllGlobals();
  });

  it("lists normalized sessions in newest-first order", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn(async () =>
        new Response(
          JSON.stringify({
            sessions: [
              { id: "old", title: "", created_at: 100, updated_at: 120 },
              { id: "new", title: " 新会话 ", created_at: 200, updated_at: 210, run_status: "running" }
            ]
          }),
          { status: 200 }
        )
      )
    );

    const sessions = await createAgentApiClient("http://agent.local").listSessions();

    expect(sessions).toEqual([
      {
        id: "new",
        title: "新会话",
        createdAt: 200,
        updatedAt: 210,
        status: undefined,
        parentSessionId: undefined,
        isStreaming: undefined,
        runStatus: "running"
      },
      {
        id: "old",
        title: "新对话",
        createdAt: 100,
        updatedAt: 120,
        status: undefined,
        parentSessionId: undefined,
        isStreaming: undefined,
        runStatus: undefined
      }
    ]);
  });

  it("returns null when loading a missing session", async () => {
    vi.stubGlobal("fetch", vi.fn(async () => new Response(JSON.stringify({ message: "missing" }), { status: 404 })));

    await expect(createAgentApiClient("http://agent.local").loadSession("missing")).resolves.toBeNull();
  });

  it("falls back when a candidate is not the agent service", async () => {
    const fetchMock = vi
      .fn()
      .mockResolvedValueOnce(new Response(JSON.stringify({ message: "not found" }), { status: 404 }))
      .mockResolvedValueOnce(
        new Response(
          JSON.stringify({
            schema_version: "agent-ui-registry@1",
            chart_grammars: [],
            components: [],
            actions: []
          }),
          { status: 200 }
        )
      );
    vi.stubGlobal("fetch", fetchMock);

    await expect(createAgentApiClient(["http://not-agent.local", "http://agent.local"]).getUiRegistry()).resolves.toEqual({
      schema_version: "agent-ui-registry@1",
      chart_grammars: [],
      components: [],
      actions: []
    });
    expect(fetchMock).toHaveBeenNthCalledWith(
      1,
      "http://not-agent.local/api/v1/agent/chat/ui-registry",
      undefined
    );
    expect(fetchMock).toHaveBeenNthCalledWith(2, "http://agent.local/api/v1/agent/chat/ui-registry", undefined);
  });

  it("sends title update payloads using backend field names", async () => {
    const fetchMock = vi.fn(async () => new Response(JSON.stringify({ ok: true }), { status: 200 }));
    vi.stubGlobal("fetch", fetchMock);

    await createAgentApiClient("http://agent.local").updateSessionTitle("session-1", "  标题  ", {
      isTitleManuallyEdited: true
    });

    expect(fetchMock).toHaveBeenCalledWith(
      "http://agent.local/api/v1/agent/chat/session/session-1/title",
      expect.objectContaining({
        method: "PATCH",
        body: JSON.stringify({
          title: "标题",
          is_title_manually_edited: true
        })
      })
    );
  });

  it("streams session events from the backend SSE endpoint", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn(async () =>
        new Response(
          [
            'event: state\ndata: {"session_id":"session-1","messages":[{"id":"u1","role":"user","parts":[{"type":"text","text":"检查压力"}]}],"is_streaming":true,"run_status":"running"}\n\n',
            'event: token\ndata: {"session_id":"session-1","content":"处理中"}\n\n',
            'event: done\ndata: {"session_id":"session-1","duration_ms":20}\n\n'
          ].join(""),
          { status: 200 }
        )
      )
    );
    const events: unknown[] = [];

    await createAgentApiClient("http://agent.local").streamSession("session-1", {
      onEvent: (event) => events.push(event)
    });

    expect(events).toEqual([
      {
        type: "state",
        sessionId: "session-1",
        messages: [{ id: "u1", role: "user", parts: [{ type: "text", text: "检查压力" }] }],
        isStreaming: true,
        runStatus: "running"
      },
      {
        type: "token",
        sessionId: "session-1",
        data: { session_id: "session-1", content: "处理中" }
      },
      {
        type: "done",
        sessionId: "session-1",
        data: { session_id: "session-1", duration_ms: 20 }
      }
    ]);
  });
});
