import { afterEach, describe, expect, it, vi } from "vitest";
import {
  copyTreeCommand,
  createDocumentCommand,
  deleteDocumentCommand,
  embedDocumentCommand,
  moveDocumentCommand,
  purgeDocumentCommand,
  renameDocumentCommand,
  restoreDocumentCommand,
  updatePageOptionsCommand,
  updatePageTitleCommand,
} from "@/lib/documents/tree-command-client";

describe("tree-command-client", () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("通过统一 client 发送 tree/document command 并返回结果", async () => {
    const fetchMock = vi.spyOn(globalThis, "fetch").mockResolvedValue({
      ok: true,
      json: async () => ({ ok: true, success: true, items: [], id: "doc_created", documentId: "doc_created" }),
    } as Response);

    await createDocumentCommand(null);
    await renameDocumentCommand({ documentId: "doc_1", title: "新标题" });
    await moveDocumentCommand({ documentId: "doc_1", parentId: null, position: 0 });
    await deleteDocumentCommand({ documentId: "doc_1" });
    await restoreDocumentCommand({ documentId: "doc_1" });
    await purgeDocumentCommand({ documentId: "doc_1" });
    await embedDocumentCommand({ sourceId: "doc_1", targetId: "doc_2" });
    await copyTreeCommand({ targetParentId: null, items: [{ documentId: "doc_1", recursive: true }] });
    await updatePageTitleCommand({ documentId: "doc_1", title: "页面标题" });
    await updatePageOptionsCommand({
      documentId: "doc_1",
      pageOptions: {
        wideLayout: true,
      },
    });

    expect(fetchMock).toHaveBeenCalledTimes(10);
    expect(fetchMock.mock.calls.map((call) => String(call[0]))).toEqual([
      "/api/tree/commands",
      "/api/tree/commands",
      "/api/tree/commands",
      "/api/documents/delete",
      "/api/documents/restore",
      "/api/documents/purge",
      "/api/documents/embed",
      "/api/documents/copy-tree",
      "/api/documents/title",
      "/api/documents/options",
    ]);

    expect(JSON.parse(String(fetchMock.mock.calls[0]?.[1]?.body))).toEqual({
      action: "create",
      parentId: null,
    });
    expect(JSON.parse(String(fetchMock.mock.calls[1]?.[1]?.body))).toEqual({
      action: "rename",
      documentId: "doc_1",
      workspaceId: null,
      title: "新标题",
    });
    expect(JSON.parse(String(fetchMock.mock.calls[2]?.[1]?.body))).toEqual({
      action: "move",
      documentId: "doc_1",
      parentId: null,
      sortOrder: 0,
      workspaceId: null,
    });
  });

  it("在后端返回错误时抛出统一异常", async () => {
    vi.spyOn(globalThis, "fetch").mockResolvedValue({
      ok: false,
      json: async () => ({ error: "删除失败" }),
    } as Response);

    await expect(deleteDocumentCommand({ documentId: "doc_1" })).rejects.toThrow("删除失败");
  });
});
