import { describe, expect, it, vi } from "vitest";
import type { ConvexHttpClient } from "convex/browser";
import type { BridgeContext, CommandEnvelope } from "@/lib/documents/bridge";
import { recordBridgeCommandArtifacts } from "@/lib/documents/bridge-log";

vi.mock("@/lib/convex/api", () => ({
  api: {
    bridgeLogs: {
      recordCommandLog: "bridgeLogs.recordCommandLog",
      recordDomainEvent: "bridgeLogs.recordDomainEvent",
    },
  },
}));

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

vi.mock("@/lib/documents/bridge", () => ({
  DocumentBridgeError: class DocumentBridgeError extends Error {
    constructor(
      message: string,
      public readonly status: number,
      public readonly code: string,
      public readonly details?: unknown,
    ) {
      super(message);
      this.name = "DocumentBridgeError";
    }
  },
}));

const context: BridgeContext = {
  deploymentId: null,
  projectId: null,
  workspaceId: "ws_1",
  requestId: "req_1",
  traceId: "trace_1",
  actor: {
    actorType: "user",
    actorId: "user_1",
    sessionId: "sess_1",
  },
  source: {
    channel: "next-route",
    client: "vitest",
  },
  tenantId: null,
  authToken: null,
  idempotencyKey: "idem_1",
  validateOnly: false,
  dryRun: false,
};

const envelope: CommandEnvelope<{ documentId: string }> = {
  name: "tree.node.archive",
  commandId: "cmd_1",
  idempotencyKey: "idem_1",
  actor: context.actor,
  source: context.source,
  target: {
    workspaceId: "ws_1",
    pageId: "page_1",
  },
  payload: {
    documentId: "page_1",
  },
  reason: null,
  refs: ["test"],
  dryRun: false,
  validateOnly: false,
};

describe("bridge-log", () => {
  it("记录成功 artifact 时应把 streamDelta 同步写入 domain event payload", async () => {
    const mutation = vi.fn().mockResolvedValue({ ok: true });

    await recordBridgeCommandArtifacts({
      context,
      envelope,
      client: { mutation } as unknown as ConvexHttpClient,
      now: "2026-04-26T00:00:00.000Z",
      domainEventType: "tree.node.archived",
      commandPayload: {
        documentId: "page_1",
        streamDelta: {
          op: "remove_document",
          documentId: "page_1",
        },
      },
    });

    expect(mutation).toHaveBeenNthCalledWith(
      2,
      "bridgeLogs.recordDomainEvent",
      expect.objectContaining({
        eventType: "tree.node.archived",
        payload: expect.objectContaining({
          schema: "mnote.tree.domain_event",
          schemaVersion: 1,
          eventType: "tree.node.archived",
          aggregate: {
            type: "page",
            id: "page_1",
          },
          command_id: "cmd_1",
          command_name: "tree.node.archive",
          command: {
            id: "cmd_1",
            name: "tree.node.archive",
            idempotencyKey: "idem_1",
          },
          trace: {
            requestId: "req_1",
            traceId: "trace_1",
          },
          error: null,
          streamDelta: {
            op: "remove_document",
            documentId: "page_1",
          },
        }),
      }),
    );
  });

  it("记录 artifact 时应优先消费 Rust domainEventPlan", async () => {
    const mutation = vi.fn().mockResolvedValue({ ok: true });

    await recordBridgeCommandArtifacts({
      context,
      envelope,
      client: { mutation } as unknown as ConvexHttpClient,
      now: "2026-04-26T00:00:00.000Z",
      domainEventPlan: {
        family: "tree",
        schema: "mnote.tree.domain_event",
        schemaVersion: 1,
        eventType: "tree.subtree.moved",
        streamDelta: {
          op: "move_document",
          documentId: "page_1",
          parentId: "parent_1",
          sortOrder: 0,
        },
      },
      domainEventType: "legacy.should_not_win",
      commandPayload: {
        documentId: "page_1",
      },
    });

    expect(mutation).toHaveBeenNthCalledWith(
      2,
      "bridgeLogs.recordDomainEvent",
      expect.objectContaining({
        eventType: "tree.subtree.moved",
        payload: expect.objectContaining({
          schema: "mnote.tree.domain_event",
          schemaVersion: 1,
          eventType: "tree.subtree.moved",
          streamDelta: {
            op: "move_document",
            documentId: "page_1",
            parentId: "parent_1",
            sortOrder: 0,
          },
        }),
      }),
    );
  });
});
