import { describe, expect, it, vi } from "vitest";

vi.mock("@/lib/convex/enabled", () => ({
  isConvexEnabled: vi.fn(() => true),
}));

vi.mock("@/lib/auth/authContext", () => ({
  HttpError: class HttpError extends Error {
    status: number;

    constructor(status: number, message: string) {
      super(message);
      this.status = status;
    }
  },
  requireAuthContext: vi.fn(async () => ({
    userId: "user_1",
  })),
}));

vi.mock("@/lib/api-utils", () => ({
  apiErrorResponse: vi.fn((message: string, status = 500, details?: unknown) => ({
    message,
    status,
    details,
  })),
}));

vi.mock("@/lib/documents/page-command-adapter", () => ({
  executeDocumentCreateChildBridgeCommand: vi.fn(async () => new Response(JSON.stringify({ ok: true }))),
  executeDocumentEmbedBridgeCommand: vi.fn(async () => new Response(JSON.stringify({ ok: true }))),
  executeDocumentTemplateBridgeCommand: vi.fn(async () => new Response(JSON.stringify({ ok: true }))),
  executeDocumentEmptyTrashBridgeCommand: vi.fn(async () => new Response(JSON.stringify({ ok: true }))),
  executeDocumentPurgeBridgeCommand: vi.fn(async () => new Response(JSON.stringify({ ok: true }))),
}));

vi.mock("@/lib/documents/page-write-command-adapter", () => ({
  executePageWriteBridgeCommand: vi.fn(async () => ({
    requestId: "req_1",
    traceId: "trace_1",
    commandId: "cmd_1",
    commandName: "page.command",
    revision: 1,
    conflictDetectionKey: "doc_1:1",
  })),
}));

vi.mock("@/lib/documents/page-aggregate-loader", () => ({
  loadPageAggregate: vi.fn(async () => ({
    page: {
      identity: { documentId: "doc_1", workspaceId: "ws_1" },
      head: {
        title: "页面标题",
        updatedAt: null,
        permissions: {
          readOnly: false,
          disableDownload: false,
          disableCopy: false,
        },
      },
      layout: { pageOptions: { wideLayout: false } },
      body: { content: null, revision: 0, conflictDetectionKey: "doc_1:0" },
      tree: { pageSubtree: null },
      stats: null,
    },
    bridge: {
      requestId: "req_1",
      traceId: "trace_1",
      queryName: "documents.page.get",
    },
  })),
}));

import { POST as postCreateChild } from "@/app/api/documents/create-child/route";
import { POST as postEmbed } from "@/app/api/documents/embed/route";
import { POST as postTemplate } from "@/app/api/documents/template/route";
import { POST as postEmptyTrash } from "@/app/api/documents/empty-trash/route";
import { POST as postPurge } from "@/app/api/documents/purge/route";
import { POST as postTitle } from "@/app/api/documents/title/route";
import { POST as postOptions } from "@/app/api/documents/options/route";
import { POST as postSave } from "@/app/api/documents/save/route";
import { POST as postCreate } from "@/app/api/documents/create/route";
import { POST as postMove } from "@/app/api/documents/move/route";
import { GET as getPage } from "@/app/api/documents/page/route";
import {
  executeDocumentCreateChildBridgeCommand,
  executeDocumentEmbedBridgeCommand,
  executeDocumentTemplateBridgeCommand,
  executeDocumentEmptyTrashBridgeCommand,
  executeDocumentPurgeBridgeCommand,
} from "@/lib/documents/page-command-adapter";
import { executePageWriteBridgeCommand } from "@/lib/documents/page-write-command-adapter";
import { loadPageAggregate } from "@/lib/documents/page-aggregate-loader";

describe("documents route adapters", () => {
  it("create route 作为 compat 壳委托 tree commands 主路径", async () => {
    const fetchMock = vi.spyOn(globalThis, "fetch").mockResolvedValue(
      new Response(
        JSON.stringify({
          requestId: "req_tree_create_1",
          traceId: "trace_tree_create_1",
          result: {
            action: "create",
            workspaceId: "ws_1",
            documentId: "doc_new",
            parentId: null,
            title: "无标题",
            sortOrder: 0,
            updatedAt: "2026-04-23T00:00:00Z",
            execution: {
              access_scope: "private",
              is_template: false,
              created_at: "2026-04-23T00:00:00Z",
              updated_at: "2026-04-23T00:00:00Z",
            },
          },
        }),
        { status: 200, headers: { "content-type": "application/json" } },
      ),
    );

    const response = await postCreate(new Request("http://localhost/api/documents/create", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ parentId: null }),
    }));
    const payload = await response.json() as {
      id: string;
      workspace_id: string;
      meta: { commandName: string };
    };

    expect(fetchMock).toHaveBeenCalledWith(
      "http://localhost/api/tree/commands",
      expect.objectContaining({
        method: "POST",
        headers: expect.any(Headers),
        body: JSON.stringify({
          action: "create",
          parentId: null,
        }),
      }),
    );
    expect(payload.id).toBe("doc_new");
    expect(payload.workspace_id).toBe("ws_1");
    expect(payload.meta.commandName).toBe("tree.node.create");
  });

  it("move route 作为 compat 壳委托 tree commands 主路径", async () => {
    const fetchMock = vi.spyOn(globalThis, "fetch").mockResolvedValue(
      new Response(
        JSON.stringify({
          requestId: "req_tree_move_1",
          traceId: "trace_tree_move_1",
          result: {
            action: "move",
            workspaceId: "ws_1",
            documentId: "doc_1",
            parentId: "parent_1",
            sortOrder: 2,
            updatedAt: "2026-04-23T00:00:00Z",
          },
        }),
        { status: 200, headers: { "content-type": "application/json" } },
      ),
    );

    const response = await postMove(new Request("http://localhost/api/documents/move", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ documentId: "doc_1", parentId: "parent_1", position: 2.7, workspaceId: "ws_1" }),
    }));
    const payload = await response.json() as {
      ok: boolean;
      meta: { commandName: string };
    };

    expect(fetchMock).toHaveBeenCalledWith(
      "http://localhost/api/tree/commands",
      expect.objectContaining({
        method: "POST",
        headers: expect.any(Headers),
        body: JSON.stringify({
          action: "move",
          documentId: "doc_1",
          parentId: "parent_1",
          sortOrder: 2,
          workspaceId: "ws_1",
        }),
      }),
    );
    expect(payload.ok).toBe(true);
    expect(payload.meta.commandName).toBe("tree.subtree.move");
  });

  it("title route 在树重命名兼容请求下委托 tree commands 主路径", async () => {
    const fetchMock = vi.spyOn(globalThis, "fetch").mockResolvedValue(
      new Response(
        JSON.stringify({
          requestId: "req_tree_rename_1",
          traceId: "trace_tree_rename_1",
          result: {
            action: "rename",
            workspaceId: "ws_1",
            documentId: "doc_1",
            title: "新标题",
            updatedAt: "2026-04-23T00:00:00Z",
          },
        }),
        { status: 200, headers: { "content-type": "application/json" } },
      ),
    );

    const response = await postTitle(new Request("http://localhost/api/documents/title", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ documentId: "doc_1", workspaceId: "ws_1", title: "新标题" }),
    }));
    const payload = await response.json() as {
      ok: boolean;
      meta: { commandName: string };
    };

    expect(fetchMock).toHaveBeenCalledWith(
      "http://localhost/api/tree/commands",
      expect.objectContaining({
        method: "POST",
        headers: expect.any(Headers),
        body: JSON.stringify({
          action: "rename",
          documentId: "doc_1",
          workspaceId: "ws_1",
          title: "新标题",
        }),
      }),
    );
    expect(payload.ok).toBe(true);
    expect(payload.meta.commandName).toBe("tree.node.rename");
  });

  it("creates child route delegates to unified adapter", async () => {
    await postCreateChild(new Request("http://localhost/api/documents/create-child", {
      method: "POST",
      body: JSON.stringify({ parentId: null }),
    }));
    expect(executeDocumentCreateChildBridgeCommand).toHaveBeenCalled();
  });

  it("embed route delegates to unified adapter", async () => {
    await postEmbed(new Request("http://localhost/api/documents/embed", {
      method: "POST",
      body: JSON.stringify({ sourceId: "doc_1", targetId: "doc_2" }),
    }));
    expect(executeDocumentEmbedBridgeCommand).toHaveBeenCalled();
  });

  it("template route delegates to unified adapter", async () => {
    await postTemplate(new Request("http://localhost/api/documents/template", {
      method: "POST",
      body: JSON.stringify({ documentId: "doc_1", isTemplate: true }),
    }));
    expect(executeDocumentTemplateBridgeCommand).toHaveBeenCalled();
  });

  it("empty trash route delegates to unified adapter", async () => {
    await postEmptyTrash(new Request("http://localhost/api/documents/empty-trash", {
      method: "POST",
      body: JSON.stringify({ workspaceId: "ws_1" }),
    }));
    expect(executeDocumentEmptyTrashBridgeCommand).toHaveBeenCalled();
  });

  it("purge route delegates to unified adapter", async () => {
    await postPurge(new Request("http://localhost/api/documents/purge", {
      method: "POST",
      body: JSON.stringify({ documentId: "doc_1" }),
    }));
    expect(executeDocumentPurgeBridgeCommand).toHaveBeenCalled();
  });

  it("page route delegates to unified aggregate loader", async () => {
    const response = await getPage(
      new Request("http://localhost/api/documents/page?documentId=doc_1&workspaceId=ws_1"),
    );
    const payload = await response.json() as {
      page: { identity: { documentId: string } };
      meta: { queryName: string };
    };

    expect(loadPageAggregate).toHaveBeenCalled();
    expect(response.status).toBe(200);
    expect(payload.page.identity.documentId).toBe("doc_1");
    expect(payload.meta.queryName).toBe("documents.page.get");
  });

  it("title route 在 page head 请求下仍委托 unified page write adapter", async () => {
    await postTitle(new Request("http://localhost/api/documents/title", {
      method: "POST",
      body: JSON.stringify({
        documentId: "doc_1",
        workspaceId: "ws_1",
        title: "新标题",
        commandName: "page.head.updateTitle",
      }),
    }));

    expect(executePageWriteBridgeCommand).toHaveBeenCalled();
  });

  it("options route delegates to unified page write adapter", async () => {
    await postOptions(new Request("http://localhost/api/documents/options", {
      method: "POST",
      body: JSON.stringify({ documentId: "doc_1", workspaceId: "ws_1", options: { wideLayout: true } }),
    }));

    expect(executePageWriteBridgeCommand).toHaveBeenCalled();
  });

  it("save route delegates to unified page write adapter", async () => {
    await postSave(new Request("http://localhost/api/documents/save", {
      method: "POST",
      body: JSON.stringify({ documentId: "doc_1", workspaceId: "ws_1", content: [] }),
    }));

    expect(executePageWriteBridgeCommand).toHaveBeenCalled();
  });
});
