import { describe, expect, it } from "vitest";
import type { SidebarInitialData } from "@/components/sidebar/types";
import { applyTreeStreamDelta } from "./tree-delta";

const baseSidebarData: SidebarInitialData = {
  activeWorkspaceId: "ws_1",
  workspaces: [],
  documents: [
    {
      id: "root",
      workspace_id: "ws_1",
      title: "Root",
      parent_id: null,
      sort_order: 0,
      is_starred: false,
      access_scope: "private",
      is_template: false,
      created_at: "2026-04-18T00:00:00Z",
      updated_at: null,
    },
    {
      id: "child",
      workspace_id: "ws_1",
      title: "Child",
      parent_id: "root",
      sort_order: 1,
      is_starred: false,
      access_scope: "private",
      is_template: false,
      created_at: "2026-04-18T00:00:00Z",
      updated_at: null,
    },
  ],
  kernelFileTreeProjection: {
    projectionId: "kernel_projection:file_tree:root",
    projection: "file_tree",
    rootNodeId: null,
    items: [
      {
        rowId: "doc:root",
        rowKind: "document",
        nodeId: "root",
        parentNodeId: null,
        nodeType: "page",
        projectionKind: "file_tree",
        title: "Root",
        depth: 0,
        position: 0,
        childCount: 2,
        expandable: true,
        expandedByDefault: true,
        capabilities: ["expand", "open", "select"],
        resourceMeta: {
          resourceKind: "document",
          documentId: "root",
          workspaceId: "ws_1",
          iconHint: "page",
        },
        iconHint: "page",
      },
      {
        rowId: "index:root",
        rowKind: "index",
        nodeId: "index:root",
        parentNodeId: "root",
        nodeType: "index",
        projectionKind: "file_tree",
        title: "index.md",
        depth: 1,
        position: 0,
        childCount: 0,
        expandable: false,
        expandedByDefault: false,
        capabilities: ["open", "select"],
        resourceMeta: {
          resourceKind: "index",
          documentId: "root",
          workspaceId: "ws_1",
          iconHint: "index",
        },
        iconHint: "index",
      },
    ],
    edges: [],
  },
  kernelSidebarProjection: {
    projectionId: "kernel_projection:sidebar_tree:workspace_root",
    projection: "sidebar_tree",
    rootNodeId: null,
    items: [
      {
        nodeId: "root",
        parentNodeId: null,
        nodeType: "page",
        projectionKind: "sidebar_tree",
        title: "Root",
        depth: 0,
        position: 0,
        childCount: 1,
        expandable: true,
        expandedByDefault: true,
        capabilities: [
          "expand",
          "open",
          "drag",
          "drop",
          "select",
          "create-child",
          "rename",
          "archive",
          "restore",
          "context-menu",
          "reorder",
        ],
        resourceMeta: {
          resourceKind: "document",
          documentId: "root",
          workspaceId: "ws_1",
          iconHint: "page",
        },
        iconHint: "page",
      },
      {
        nodeId: "child",
        parentNodeId: "root",
        nodeType: "page",
        projectionKind: "sidebar_tree",
        title: "Child",
        depth: 1,
        position: 1,
        childCount: 0,
        expandable: false,
        expandedByDefault: true,
        capabilities: [
          "open",
          "drag",
          "drop",
          "select",
          "create-child",
          "rename",
          "archive",
          "restore",
          "context-menu",
          "reorder",
        ],
        resourceMeta: {
          resourceKind: "document",
          documentId: "child",
          workspaceId: "ws_1",
          iconHint: "page",
        },
        iconHint: "page",
      },
    ],
    edges: [
      {
        id: "edge:root:child:parent_of",
        edgeType: "parent_of",
        workspaceId: "ws_1",
        fromNodeId: "root",
        toNodeId: "child",
      },
    ],
  },
  kernelSidebarTree: [],
  trashedDocuments: [],
  trashedMediaAssets: [],
  trashedMindmapAssets: [],
  trashedTableAssets: [],
  tableAssets: [],
  mindmapDocs: [],
  mindmapAssets: [],
  mindmapAssetChildren: {},
  mediaAssets: [],
};

describe("tree-stream/tree-delta", () => {
  it("支持 upsert_document 重建 sidebar projection", () => {
    const next = applyTreeStreamDelta(baseSidebarData, {
      op: "upsert_document",
      document: {
        id: "leaf",
        workspace_id: "ws_1",
        title: "Leaf",
        parent_id: "child",
        sort_order: 0,
        is_starred: false,
        access_scope: "private",
        is_template: false,
        created_at: "2026-04-18T00:00:00Z",
        updated_at: null,
      },
    });

    expect(next.documents.map((item) => item.id)).toEqual(["root", "child", "leaf"]);
    expect(next.kernelSidebarProjection.items.map((item) => item.nodeId)).toEqual([
      "root",
      "child",
      "leaf",
    ]);
  });

  it("支持 remove_document 级联移除子树", () => {
    const next = applyTreeStreamDelta(baseSidebarData, {
      op: "remove_document",
      documentId: "root",
    });

    expect(next.documents).toEqual([]);
    expect(next.kernelSidebarProjection.items).toEqual([]);
  });

  it("支持 replace_sidebar 直接切换到 resync snapshot", () => {
    const next = applyTreeStreamDelta(baseSidebarData, {
      op: "replace_sidebar",
      sidebar: {
        activeWorkspaceId: "ws_1",
        workspaces: [],
        documents: [],
        kernelSidebarProjection: {
          projectionId: "kernel_projection:sidebar_tree:workspace_root",
          projection: "sidebar_tree",
          rootNodeId: null,
          items: [],
          edges: [],
        },
        kernelFileTreeProjection: {
          projectionId: "kernel_projection:file_tree:root",
          projection: "file_tree",
          rootNodeId: null,
          items: [],
          edges: [],
        },
        kernelSidebarTree: [],
        trashedDocuments: [],
        trashedMediaAssets: [],
        trashedMindmapAssets: [],
        trashedTableAssets: [],
        tableAssets: [],
        mindmapDocs: [],
        mindmapAssets: [],
        mindmapAssetChildren: {},
        mediaAssets: [],
      },
    });

    expect(next.documents).toEqual([]);
    expect(next.kernelSidebarProjection.items).toEqual([]);
  });
});
