import { afterEach, describe, expect, it, vi } from "vitest";
import {
  buildWorkspaceTreeStreamUrl,
  normalizeTreeStreamSnapshot,
  parseTreeStreamMessage,
} from "./protocol";

describe("tree-stream/protocol", () => {
  afterEach(() => {
    vi.unstubAllGlobals();
  });

  it("构造 workspace sidebar stream url", () => {
    vi.stubGlobal("window", {
      ...window,
      location: {
        ...window.location,
        origin: "http://127.0.0.1:3000",
      },
    });
    expect(
      buildWorkspaceTreeStreamUrl(" ws_1 ", "evt_9"),
    ).toBe(
      "http://127.0.0.1:3000/api/mnote-web/stream?workspaceId=ws_1&cursor=evt_9",
    );
  });

  it("固定走同源 stream route", () => {
    vi.stubGlobal("window", {
      ...window,
      location: {
        ...window.location,
        origin: "http://127.0.0.1:3000",
      },
    });
    expect(
      buildWorkspaceTreeStreamUrl("ws_1", null),
    ).toBe("http://127.0.0.1:3000/api/mnote-web/stream?workspaceId=ws_1");
  });

  it("解析 snapshot / delta / resync 协议消息", () => {
    expect(
      parseTreeStreamMessage({
        eventType: "snapshot",
        rawData: JSON.stringify({
          stream: "workspace",
          workspaceId: "ws_1",
          cursor: "evt_1",
          projection: "sidebar_tree",
          data: {
            active_workspace_id: "ws_1",
            workspaces: [],
            documents: [],
            kernel_file_tree_projection: {
              projectionId: "kernel_projection:file_tree:root",
              projection: "file_tree",
              rootNodeId: null,
              items: [],
              edges: [],
            },
            kernel_sidebar_projection: {
              projectionId: "kernel_projection:sidebar_tree:workspace_root",
              projection: "sidebar_tree",
              rootNodeId: null,
              items: [],
              edges: [],
            },
            trashed_documents: [],
            media_assets: [],
            trashed_media_assets: [],
            mindmap_assets: [],
            trashed_mindmap_assets: [],
            table_assets: [],
            trashed_table_assets: [],
            mindmap_docs: [],
            mindmap_asset_children: {},
          },
        }),
      }),
    ).toMatchObject({
      kind: "snapshot",
      stream: "workspace",
      workspaceId: "ws_1",
      cursor: "evt_1",
      projection: "sidebar_tree",
    });

    expect(
      parseTreeStreamMessage({
        eventType: "delta",
        rawData: JSON.stringify({
          kind: "delta",
          workspace_id: "ws_1",
          cursor: "evt_2",
          payload: { op: "remove_document", documentId: "doc_1" },
        }),
      }),
    ).toMatchObject({
      kind: "delta",
      workspaceId: "ws_1",
      cursor: "evt_2",
      data: { op: "remove_document", documentId: "doc_1" },
    });
  });

  it("把 sidebar.dataset.list snapshot 归一化成 SidebarInitialData", () => {
    const snapshot = normalizeTreeStreamSnapshot({
      active_workspace_id: "ws_1",
      workspaces: [],
      documents: [],
      kernel_file_tree_projection: {
        projectionId: "kernel_projection:file_tree:root",
        projection: "file_tree",
        rootNodeId: null,
        items: [],
        edges: [],
      },
      kernel_sidebar_projection: {
        projectionId: "kernel_projection:sidebar_tree:workspace_root",
        projection: "sidebar_tree",
        rootNodeId: null,
        items: [],
        edges: [],
      },
      trashed_documents: [],
      media_assets: [],
      trashed_media_assets: [],
      mindmap_assets: [],
      trashed_mindmap_assets: [],
      table_assets: [],
      trashed_table_assets: [],
      mindmap_docs: [],
      mindmap_asset_children: {},
    });

    expect(snapshot).toMatchObject({
      activeWorkspaceId: "ws_1",
      kernelFileTreeProjection: {
        projection: "file_tree",
      },
      kernelSidebarProjection: {
        projection: "sidebar_tree",
      },
    });
  });
});
