import { describe, expect, it } from "vitest";
import { buildKernelFileTreeProjection } from "@/lib/kernel-file-tree";
import {
  buildSidebarDataSyncKey,
  buildSidebarTreeSyncKey,
  buildMediaAssetListSyncKey,
  getSidebarDataFreshness,
} from "./sidebar-sync";
import type { DocumentRecord } from "@/lib/documents";
import type { SidebarInitialData } from "@/components/sidebar/types";
import type { SidebarTreeNode } from "@/lib/kernel-sidebar";
import type { MediaAsset } from "@/types/media";

function buildNode(overrides: Partial<SidebarTreeNode> = {}): SidebarTreeNode {
  return {
    id: "doc-1",
    workspace_id: "ws-1",
    title: "标题",
    parent_id: null,
    sort_order: 0,
    is_starred: false,
    is_template: false,
    access_scope: "private",
    created_at: "2026-04-21T00:00:00.000Z",
    updated_at: "2026-04-21T00:00:00.000Z",
    children: [],
    kernel: {
      nodeType: "page",
      depth: 0,
      position: 0,
      childCount: 0,
      expandedByDefault: true,
    },
    ...overrides,
  };
}

function buildAsset(overrides: Partial<MediaAsset> = {}): MediaAsset {
  return {
    id: "asset-1",
    workspace_id: "ws-1",
    document_id: "doc-1",
    asset_type: "image",
    file_url: "/files/a.png",
    thumbnail_url: null,
    bucket: null,
    storage_path: "uploads/a.png",
    file_name: "a.png",
    file_size: 1,
    mime_type: "image/png",
    ocr_payload: undefined,
    ocr_strategy: null,
    ocr_text: null,
    ocr_status: null,
    signed_url: null,
    created_at: "2026-04-21T00:00:00.000Z",
    updated_at: "2026-04-21T00:00:00.000Z",
    ...overrides,
  };
}

function buildDocument(overrides: Partial<DocumentRecord> = {}): DocumentRecord {
  return {
    access_scope: "private",
    id: "doc-1",
    workspace_id: "ws-1",
    title: "标题",
    parent_id: null,
    sort_order: 0,
    is_starred: false,
    is_template: false,
    created_at: "2026-04-21T00:00:00.000Z",
    updated_at: "2026-04-21T00:00:00.000Z",
    ...overrides,
  };
}

function buildSidebarData(documents: DocumentRecord[]): SidebarInitialData {
  return {
    activeWorkspaceId: "ws-1",
    workspaces: [],
    documents,
    kernelSidebarProjection: {
      projectionId: "kernel_projection:sidebar_tree:workspace_root",
      projection: "sidebar_tree",
      rootNodeId: null,
      items: [],
      edges: [],
    },
    kernelSidebarTree: [],
    kernelFileTreeProjection: buildKernelFileTreeProjection({
      documents: [],
      mediaAssets: [],
      mindmapAssets: [],
      tableAssets: [],
      mindmapAssetChildren: {},
    }),
    trashedDocuments: [],
    trashedMediaAssets: [],
    trashedMindmapAssets: [],
    trashedTableAssets: [],
    tableAssets: [],
    mindmapDocs: [],
    mindmapAssets: [],
    mindmapAssetChildren: {},
    mediaAssets: [],
  };
}

describe("sidebar-sync", () => {
  it("相同侧边栏树内容应产生相同 sync key", () => {
    const left = [buildNode({ children: [buildNode({ id: "doc-2", parent_id: "doc-1" })] })];
    const right = [buildNode({ children: [buildNode({ id: "doc-2", parent_id: "doc-1" })] })];

    expect(buildSidebarTreeSyncKey(left)).toBe(buildSidebarTreeSyncKey(right));
  });

  it("侧边栏树语义变化时应产生不同 sync key", () => {
    const left = [buildNode({ title: "标题 A" })];
    const right = [buildNode({ title: "标题 B" })];

    expect(buildSidebarTreeSyncKey(left)).not.toBe(buildSidebarTreeSyncKey(right));
  });

  it("相同附件列表内容应产生相同 sync key", () => {
    const left = [buildAsset()];
    const right = [buildAsset()];

    expect(buildMediaAssetListSyncKey(left)).toBe(buildMediaAssetListSyncKey(right));
  });

  it("附件列表语义变化时应产生不同 sync key", () => {
    const left = [buildAsset({ file_name: "a.png" })];
    const right = [buildAsset({ file_name: "b.png" })];

    expect(buildMediaAssetListSyncKey(left)).not.toBe(buildMediaAssetListSyncKey(right));
  });

  it("顶层 documents 变化应影响 sidebar data sync key", () => {
    const left = buildSidebarData([]);
    const right = buildSidebarData([buildDocument({ id: "doc-live", title: "显式刷新标题" })]);

    expect(buildSidebarDataSyncKey(left)).not.toBe(buildSidebarDataSyncKey(right));
  });

  it("file tree position 不应被当作 freshness 时间戳压住新 snapshot", () => {
    const stale = buildSidebarData([buildDocument({
      id: "old",
      created_at: "2026-05-13T00:00:00.000Z",
      updated_at: "2026-05-13T00:00:00.000Z",
    })]);
    stale.kernelFileTreeProjection = {
      ...stale.kernelFileTreeProjection,
      items: [
        {
          projectionKind: "file_tree",
          rowId: "doc:old",
          rowKind: "document",
          nodeId: "old",
          parentNodeId: null,
          nodeType: "page",
          title: "旧页面",
          depth: 0,
          position: Number.MAX_SAFE_INTEGER,
          childCount: 0,
          expandable: false,
          expandedByDefault: false,
          capabilities: ["open"],
          resourceMeta: {
            resourceKind: "document",
            documentId: "old",
            workspaceId: "ws-1",
            iconHint: "page",
          },
          iconHint: "page",
        },
      ],
    };
    const fresh = buildSidebarData([buildDocument({
      id: "new",
      created_at: "2026-05-14T00:00:00.000Z",
      updated_at: "2026-05-14T00:00:00.000Z",
    })]);

    expect(getSidebarDataFreshness(fresh)).toBeGreaterThan(getSidebarDataFreshness(stale));
  });
});
