import {
  blocksFromTiptapDoc,
  editorBlockDocumentFromContent,
  editorBlockDocumentFromTiptapDoc,
  tiptapDocFromBlocks,
  tiptapDocFromEditorBlockDocument,
} from "@/lib/documents/tiptap-content-converter";
import { describe, expect, it } from "vitest";

describe("tiptap-content-converter", () => {
  it("keeps empty content editable", () => {
    expect(tiptapDocFromBlocks([])).toEqual({
      type: "doc",
      content: [{ type: "paragraph", attrs: {}, content: [] }],
    });
    expect(blocksFromTiptapDoc({ type: "doc", content: [] })).toEqual([]);
  });

  it("preserves stable block ids through paragraph round-trip", () => {
    const blocks = [{ id: "p1", type: "paragraph", content: "你好，世界" }];
    expect(blocksFromTiptapDoc(tiptapDocFromBlocks(blocks as never))).toEqual([
      { id: "p1", type: "paragraph", props: undefined, content: "你好，世界" },
    ]);
  });

  it("把 BlockNote inline text 数组转换成 TipTap 可编辑文本节点", () => {
    expect(
      tiptapDocFromBlocks([
        {
          id: "cli_visible_b_b2",
          type: "paragraph",
          content: [{ type: "text", text: "第二个 CLI 页面，可直接编辑。" }],
        },
      ] as never),
    ).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: { blockId: "cli_visible_b_b2" },
          content: [{ type: "text", text: "第二个 CLI 页面，可直接编辑。" }],
        },
      ],
    });
  });

  it("round-trips p0.5 block families through editor block document", () => {
    const document = editorBlockDocumentFromContent([
      { id: "p1", type: "paragraph", content: "段落" },
      { id: "h1", type: "heading", props: { level: 2 }, content: "标题" },
      { id: "b1", type: "bullet_list_item", content: "项目" },
      { id: "n1", type: "numbered_list_item", content: "序号" },
      { id: "t1", type: "todo", props: { checked: true }, content: "待办" },
      { id: "q1", type: "quote", content: "引用" },
      { id: "c1", type: "code_block", props: { language: "ts" }, content: "const x = 1" },
    ] as never);

    const tiptapDoc = tiptapDocFromEditorBlockDocument(document);
    const roundTrip = editorBlockDocumentFromTiptapDoc(tiptapDoc, "doc-1");

    expect(roundTrip.rootBlockIds).toEqual(["p1", "h1", "b1", "n1", "t1", "q1", "c1"]);
    expect(roundTrip.blocks.map((block) => [block.blockId, block.blockType])).toEqual([
      ["p1", "paragraph"],
      ["h1", "heading"],
      ["b1", "bullet_list_item"],
      ["n1", "numbered_list_item"],
      ["t1", "todo"],
      ["q1", "quote"],
      ["c1", "code_block"],
    ]);
    expect(roundTrip.blocks[1].props?.headingLevel).toBe(2);
    expect(roundTrip.blocks[4].props?.checked).toBe(true);
    expect(roundTrip.blocks[6].props?.language).toBe("ts");
  });

  it("将 legacy media block 转成带链接的可见段落文本", () => {
    expect(
      tiptapDocFromBlocks([
        {
          id: "m1",
          type: "media",
          props: { name: "Spec", sourcePath: "assets/spec.pdf" },
          content: [],
        },
      ] as never),
    ).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: { blockId: "m1" },
          content: [
            {
              type: "text",
              text: "Spec",
              marks: [{ type: "link", attrs: { href: "assets/spec.pdf" } }],
            },
          ],
        },
      ],
    });
  });

  it("legacy media block 在 sourcePath 为空时使用 url 作为链接", () => {
    expect(
      tiptapDocFromBlocks([
        {
          id: "m-url",
          type: "media",
          props: { name: "Spec", sourcePath: "", url: "assets/from-url.pdf" },
          content: [],
        },
      ] as never),
    ).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: { blockId: "m-url" },
          content: [
            {
              type: "text",
              text: "Spec",
              marks: [{ type: "link", attrs: { href: "assets/from-url.pdf" } }],
            },
          ],
        },
      ],
    });
  });

  it("legacy media block 在 name 为空时使用 fileName 作为可见文本", () => {
    expect(
      tiptapDocFromBlocks([
        {
          id: "m-file-name",
          type: "media",
          props: { name: "", fileName: "Fallback Name", sourcePath: "assets/spec.pdf" },
          content: [],
        },
      ] as never),
    ).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: { blockId: "m-file-name" },
          content: [
            {
              type: "text",
              text: "Fallback Name",
              marks: [{ type: "link", attrs: { href: "assets/spec.pdf" } }],
            },
          ],
        },
      ],
    });
  });

  it("legacy media block 会继续 fallback 到 src 和 title", () => {
    expect(
      tiptapDocFromBlocks([
        {
          id: "m-src-title",
          type: "media",
          props: {
            sourcePath: "",
            url: "",
            src: "assets/from-src.pdf",
            name: "",
            fileName: "",
            title: "Fallback Title",
          },
          content: [],
        },
      ] as never),
    ).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: { blockId: "m-src-title" },
          content: [
            {
              type: "text",
              text: "Fallback Title",
              marks: [{ type: "link", attrs: { href: "assets/from-src.pdf" } }],
            },
          ],
        },
      ],
    });
  });

  it("legacy media block 的链接 mark 在 TipTap 往返和 legacy 输出中不丢失", () => {
    const tiptapDoc = tiptapDocFromBlocks([
      {
        id: "m-round-trip",
        type: "media",
        props: { name: "Spec", sourcePath: "assets/spec.pdf" },
        content: [],
      },
    ] as never);

    expect(tiptapDocFromEditorBlockDocument(editorBlockDocumentFromTiptapDoc(tiptapDoc))).toEqual(tiptapDoc);
    expect(blocksFromTiptapDoc(tiptapDoc)).toEqual([
      {
        id: "m-round-trip",
        type: "paragraph",
        props: undefined,
        content: [
          {
            type: "text",
            text: "Spec",
            styles: { link: "assets/spec.pdf" },
          },
        ],
      },
    ]);
  });

  it("保留 mindmap 引用骨架为 mindmap legacy block，不把图数据写回文档块", () => {
    const tiptapDoc = {
      type: "doc" as const,
      content: [
        {
          type: "paragraph",
          attrs: {
            blockId: "mind_1",
            mnoteBlockType: "mindmap",
            mindmapId: "mindmap_1",
            rootNodeId: "root",
            projectionVersion: 1,
            mnoteMindmapData: {
              data: { uid: "root", text: "KMIND", generalization: { text: "概要" } },
              children: [
                {
                  data: { uid: "topic", text: "二级节点" },
                  children: [
                    { data: { uid: "branch-1", text: "分支主题" }, children: [] },
                    { data: { uid: "branch-2", text: "分支主题" }, children: [] },
                  ],
                },
              ],
            },
          },
          content: [{ type: "text", text: "KMIND / 二级节点 / 分支主题 / 分支主题 / 概要" }],
        },
      ],
    };

    expect(blocksFromTiptapDoc(tiptapDoc)).toEqual([
      {
        id: "mind_1",
        type: "mindmap",
        props: {
          mindmapId: "mindmap_1",
          rootNodeId: "root",
          projectionVersion: 1,
        },
        content: "",
      },
    ]);
  });

  it("读取旧 mindmap block 时只迁移引用字段，丢弃 props.data 作为块真源", () => {
    const tiptapDoc = tiptapDocFromBlocks([
      {
        id: "mind_legacy",
        type: "mindmap",
        props: {
          data: { id: "mindmap_from_legacy_data", rootNodeId: "root_from_data" },
        },
      },
    ] as never);

    expect(tiptapDoc).toEqual({
      type: "doc",
      content: [
        {
          type: "paragraph",
          attrs: {
            blockId: "mind_legacy",
            mnoteBlockType: "mindmap",
            mindmapId: "mindmap_from_legacy_data",
            rootNodeId: "root_from_data",
          },
        },
      ],
    });
    expect(blocksFromTiptapDoc(tiptapDoc)).toEqual([
      {
        id: "mind_legacy",
        type: "mindmap",
        props: {
          mindmapId: "mindmap_from_legacy_data",
          rootNodeId: "root_from_data",
        },
        content: "",
      },
    ]);
  });

  it("mindmap 引用多轮 TipTap/legacy 转换时保持 mindmapId 稳定", () => {
    const original = {
      type: "doc" as const,
      content: [
        {
          type: "paragraph",
          attrs: {
            blockId: "mind_block_stable",
            mnoteBlockType: "mindmap",
            mindmapId: "mindmap_stable_1",
            rootNodeId: "root",
          },
          content: [{ type: "text", text: "中心主题" }],
        },
      ],
    };

    const firstLegacy = blocksFromTiptapDoc(original);
    const secondTiptap = tiptapDocFromBlocks(firstLegacy as never);
    const secondLegacy = blocksFromTiptapDoc(secondTiptap);
    const thirdTiptap = tiptapDocFromBlocks(secondLegacy as never);

    expect(firstLegacy[0]?.props?.mindmapId).toBe("mindmap_stable_1");
    expect(secondLegacy[0]?.props?.mindmapId).toBe("mindmap_stable_1");
    expect(secondTiptap.content?.[0]?.attrs?.mindmapId).toBe("mindmap_stable_1");
    expect(thirdTiptap.content?.[0]?.attrs?.mindmapId).toBe("mindmap_stable_1");
    expect(thirdTiptap.content?.[0]?.attrs?.blockId).toBe("mind_block_stable");
  });

});
