import { afterEach, describe, expect, it, vi } from "vitest";
import type { ConvexHttpClient } from "convex/browser";

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/convex/api", () => ({
  api: {
    documents: {
      getContent: "documents:getContent",
    },
  },
}));

vi.mock("@/lib/convex/route", () => ({
  getAuthedConvexClient: vi.fn(),
}));

vi.mock("@/lib/documents/bridge-log", () => ({
  recordBridgeCommandArtifacts: vi.fn(),
  recordBridgeCommandFailureArtifacts: vi.fn(),
  recordRustBridgeCommandArtifacts: vi.fn(),
}));

vi.mock("@/lib/documents/rust-runtime", () => ({
  resolveRustBridgeCommandPlan: vi.fn(),
  resolveRustBridgeQueryPlan: vi.fn(),
  executeRustBridgeQueryTransport: vi.fn(),
  executeRustBridgeMutationTransport: vi.fn(),
}));

vi.mock("@/lib/document-content", () => ({
  extractBlocksFromContent: vi.fn(),
}));

afterEach(() => {
  vi.clearAllMocks();
});

describe("documents/block-command-adapter", () => {
  it("executeBlockPatchBridgeCommand 应改走 Rust artifact writer", async () => {
    const { getAuthedConvexClient } = await import("@/lib/convex/route");
    const {
      recordBridgeCommandArtifacts,
      recordRustBridgeCommandArtifacts,
    } = await import("@/lib/documents/bridge-log");
    const {
      resolveRustBridgeCommandPlan,
      executeRustBridgeMutationTransport,
    } = await import("@/lib/documents/rust-runtime");
    const { extractBlocksFromContent } = await import("@/lib/document-content");
    const { executeBlockPatchBridgeCommand } = await import("./block-command-adapter");

    vi.mocked(getAuthedConvexClient).mockResolvedValue({
      auth: { userId: "user_1" },
      client: {
        query: vi.fn().mockResolvedValue({
          content: { type: "doc" },
        }),
        mutation: vi.fn(),
      } as unknown as ConvexHttpClient,
    });
    vi.mocked(extractBlocksFromContent).mockReturnValue([
      {
        id: "blk_1",
        type: "paragraph",
      },
    ]);
    vi.mocked(resolveRustBridgeCommandPlan).mockResolvedValue({
      kind: "command",
      commandName: "blocks.patch",
      commandId: "cmd_block_patch_1",
      functionName: "documents:updateContent",
      workspaceId: "ws_1",
      requestId: "req_1",
      traceId: "trace_1",
      actorId: "user_1",
      idempotencyKey: "idem_1",
      payloadJson: "{\"kind\":\"command\"}",
      argsJson: {
        id: "doc_1",
        blockId: "blk_1",
        nextBlock: {
          id: "blk_1",
          type: "heading",
        },
      },
    });
    vi.mocked(executeRustBridgeMutationTransport).mockResolvedValue({
      revision: 8,
      conflict_detection_key: "doc_1:8",
    });

    const result = await executeBlockPatchBridgeCommand({
      request: new Request("http://127.0.0.1:3000/api/documents/blocks/patch", {
        method: "POST",
      }),
      sourceDocumentId: "doc_1",
      workspaceId: "ws_1",
      blockId: "blk_1",
      nextBlock: {
        id: "blk_1",
        type: "heading",
      },
    });

    expect(result.commandName).toBe("blocks.patch");
    expect(recordRustBridgeCommandArtifacts).toHaveBeenCalledWith({
      client: expect.any(Object),
      context: expect.objectContaining({
        workspaceId: "ws_1",
      }),
      envelope: expect.objectContaining({
        name: "blocks.patch",
      }),
      plan: expect.objectContaining({
        commandName: "blocks.patch",
      }),
      result: {
        revision: 8,
        conflict_detection_key: "doc_1:8",
      },
    });
    expect(recordBridgeCommandArtifacts).not.toHaveBeenCalled();
  });
});
