import { describe, expect, it, vi } from "vitest";
import {
  createMindmapAdapterProjectionEndpoint,
  createMindmapCommandApplyEndpoint,
  executeMindmapCommandApply,
  executeMindmapCommandApplyAndRefreshProjection,
  executeMindmapDataPutAndRefreshProjection,
  isMindmapAdapterProjection,
  requestMindmapAdapterProjection,
} from "./leptos-mindmap-adapter";
import { createFallbackMindmapAdapterProjection } from "./simple-mind-map-bridge";

describe("leptos-mindmap adapter projection", () => {
  it("识别 adapter projection contract", () => {
    const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1" });
    expect(isMindmapAdapterProjection(projection)).toBe(true);
    expect(isMindmapAdapterProjection({ ...projection, runtime: "other" })).toBe(false);
  });

  it("构建 simple_mind_map_scene 查询 endpoint", () => {
    expect(createMindmapAdapterProjectionEndpoint("doc 1", "mind/1")).toBe(
      "/api/mindmap/doc%201/mind%2F1?view=simple_mind_map_scene&queryName=mindmap.simple_mind_map_scene.get",
    );
    expect(createMindmapCommandApplyEndpoint("doc 1", "mind/1")).toBe(
      "/api/mindmap/doc%201/mind%2F1",
    );
  });

  it("从 result wrapper 中读取 projection", async () => {
    const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1" });
    const fetcher = vi.fn(async () => ({
      ok: true,
      json: async () => ({ result: projection }),
    })) as unknown as typeof fetch;

    await expect(
      requestMindmapAdapterProjection({
        documentId: "doc_1",
        mindmapId: "mind_1",
        fetcher,
      }),
    ).resolves.toEqual(projection);
  });

  it("command apply 成功后可刷新 adapter projection", async () => {
    const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1", kernelRevision: 12 });
    const fetcher = vi
      .fn()
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ ok: true, kernelRevision: 11 }),
      })
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ result: projection }),
      }) as unknown as typeof fetch;

    await expect(
      executeMindmapCommandApplyAndRefreshProjection({
        documentId: "doc_1",
        mindmapId: "mind_1",
        commands: [{ type: "updateText", mindmapId: "mind_1", nodeId: "root", text: "新标题" }],
        projectionRevision: 10,
        fetcher,
      }),
    ).resolves.toEqual(projection);
    expect(fetcher).toHaveBeenNthCalledWith(
      1,
      "/api/mindmap/doc_1/mind_1",
      expect.objectContaining({
        method: "POST",
        body: expect.stringContaining('"commandName":"mindmap.command.apply"'),
      }),
    );
  });

  it("command apply 失败时抛出可定位 command_failed 错误", async () => {
    const fetcher = vi.fn(async () => ({
      ok: false,
      status: 409,
      json: async () => ({ error: "revision_conflict" }),
    })) as unknown as typeof fetch;

    await expect(
      executeMindmapCommandApply({
        documentId: "doc_1",
        mindmapId: "mind_1",
        commands: [{ type: "deleteNode", mindmapId: "mind_1", nodeId: "node_1" }],
        fetcher,
      }),
    ).rejects.toMatchObject({ code: "command_failed", status: 409, message: "command_failed:409:revision_conflict" });
  });

  it("data put 失败时透出 route 错误细节", async () => {
    const fetcher = vi.fn(async () => ({
      ok: false,
      status: 400,
      json: async () => ({ error: "mindmap_put_failed", details: ["missing_root_uid"] }),
    })) as unknown as typeof fetch;

    await expect(
      executeMindmapDataPutAndRefreshProjection({
        documentId: "doc_1",
        mindmapId: "mind_1",
        data: { data: { text: "中心主题" }, children: [] },
        fetcher,
      }),
    ).rejects.toMatchObject({ code: "command_failed", status: 400, message: "command_failed:400:mindmap_put_failed" });
  });
});
