import { spawn } from "node:child_process";
import { constants as fsConstants } from "node:fs";
import { access, readdir, stat } from "node:fs/promises";
import path from "node:path";
import type { ConvexHttpClient } from "convex/browser";
import type { Id } from "../../../convex/_generated/dataModel";
import { api } from "@/lib/convex/api";
import {
  buildMindmapEditorScene,
  buildMindmapProjection,
  buildMindmapSimpleMindMapScene,
} from "@/lib/mindmap/mindmap-projection";
import {
  DocumentBridgeError,
  type BridgeTarget,
  type BridgeContext,
  type CommandEnvelope,
  type QueryEnvelope,
} from "@/lib/documents/bridge";
import { shouldUseBuiltBridgeRuntimeBinary } from "@/lib/documents/rust-runtime-selection";

export type RustRuntimeExecutedQuery<TResult = unknown> = {
  ok: true;
  result: TResult;
};

type RustRuntimeErrorKind =
  | "validation"
  | "unauthorized"
  | "conflict"
  | "not_found"
  | "transport"
  | "rejected";

type RustRuntimeErrorPayload = {
  kind: RustRuntimeErrorKind | string;
  message: string;
};

type RustRuntimeResponse =
  | {
      ok: true;
      plan: RustBridgeQueryPlan | RustBridgeCommandPlan | RustBridgeToolPlan | RustBridgeBuiltinToolPlan;
    }
  | RustRuntimeExecutedQuery
  | {
      ok: true;
      artifacts: RustBridgeCommandArtifactPlan | null;
    }
  | {
      ok: false;
      error: RustRuntimeErrorPayload;
    };

export type RustBridgeQueryPlan = {
  kind: "query";
  queryName: string;
  functionName: string;
  workspaceId: string | null;
  requestId: string;
  traceId: string;
  actorId: string;
  payloadJson: string;
  argsJson: Record<string, unknown>;
};

export type RustBridgeCommandPlan = {
  kind: "command";
  commandName: string;
  commandId: string;
  functionName: string;
  workspaceId: string | null;
  requestId: string;
  traceId: string;
  actorId: string;
  idempotencyKey: string | null;
  source?: Record<string, unknown>;
  payloadJson: string;
  argsJson: Record<string, unknown>;
};

export type RustTreeDomainEventPlan = {
  family: "tree";
  schema: "mnote.tree.domain_event";
  schemaVersion: 1;
  eventType: string;
  payload?: Record<string, unknown>;
  streamDeltaHint?: Record<string, unknown>;
  streamDelta?: RustTreeStreamDelta;
};

export type RustTreeStreamDelta =
  | {
      op: "noop";
    }
  | {
      op: "resync_required";
      reason?: string;
      pageId?: string;
      documentId?: string;
      blockId?: string;
    }
  | {
      op: "upsert_document";
      document: Record<string, unknown>;
    }
  | {
      op: "upsert_documents";
      upsertDocuments: Record<string, unknown>[];
    }
  | {
      op: "remove_document";
      documentId: string;
    }
  | {
      op: "move_document";
      documentId: string;
      parentId: string | null;
      sortOrder: number;
      updatedAt?: string;
    }
  | {
      op: "upsert_assets";
      upsertAssets: Record<string, unknown>[];
    };

export type RustBridgeCommandLogArtifactPlan = {
  workspaceId: string;
  id: string;
  requestId: string;
  traceId: string;
  commandId: string;
  commandName: string;
  actorId: string;
  actorType: string;
  sourceChannel: string;
  sourceClient: string;
  status: string;
  targetPageId: string | null;
  targetBlockId: string | null;
  payload: unknown;
  payloadSummary: string;
  refs: string[];
  idempotencyKey: string | null;
  error: string | null;
  createdAt: string;
  finishedAt: string | null;
};

export type RustBridgeDomainEventArtifactPlan = {
  workspaceId: string;
  id: string;
  requestId: string;
  traceId: string;
  commandId: string;
  commandLogId: string;
  eventType: string;
  aggregateType: string;
  aggregateId: string;
  eventVersion: number;
  status: string;
  actorType: string;
  payload: unknown;
  createdAt: string;
};

export type RustBridgeCommandArtifactPlan = {
  commandLog: RustBridgeCommandLogArtifactPlan;
  domainEvent: RustBridgeDomainEventArtifactPlan | null;
  domainEvents?: RustBridgeDomainEventArtifactPlan[];
};

export type RustBridgeToolPlanStep = {
  kind: string;
  name: string;
  functionName: string | null;
  description: string;
  argsJson: Record<string, unknown>;
};

export type RustBridgeToolPlan = {
  kind: "tool";
  toolName: string;
  invocationKind: string;
  executionMode: string;
  effect: string;
  toolsetId: string;
  requiresConfirmation: boolean;
  requestId: string;
  traceId: string;
  actorId: string;
  validateOnly: boolean;
  dryRun: boolean;
  payloadJson: string;
  argsJson: Record<string, unknown>;
  target: Record<string, unknown> | null;
  steps: RustBridgeToolPlanStep[];
};

export type RustBridgeBuiltinToolPlan = {
  kind: "builtin_tool";
  toolName: string;
  toolsetId: string;
  status: "rust" | "mixed" | "ts" | "transport";
  note: string;
};

export type RustBridgeToolResult<TResult = unknown> = {
  plan: RustBridgeToolPlan;
  result: TResult;
};

type RuntimeProcessResult = {
  code: number | null;
  signal: NodeJS.Signals | null;
  stdout: string;
  stderr: string;
};

type RuntimeInvocation = {
  command: string;
  args: string[];
};

const RUST_RUNTIME_TIMEOUT_MS = 30_000;
const RUST_RUNTIME_FALLBACK_TOOLCHAIN = "1.89.0";

export function resolveRustRuntimeProcessEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
  const explicitToolchain = env.RUSTUP_TOOLCHAIN?.trim() || env.MNOTE_RUST_BRIDGE_TOOLCHAIN?.trim();

  return {
    ...env,
    CARGO_TERM_COLOR: "never",
    RUSTUP_TOOLCHAIN: explicitToolchain || RUST_RUNTIME_FALLBACK_TOOLCHAIN,
  };
}

async function pathExists(targetPath: string) {
  try {
    await access(targetPath, fsConstants.F_OK);
    return true;
  } catch {
    return false;
  }
}

async function resolveRepoRoot() {
  const candidates = [process.cwd(), path.resolve(process.cwd(), "..")];
  for (const candidate of candidates) {
    if (await pathExists(path.join(candidate, "rust", "Cargo.toml"))) {
      return candidate;
    }
  }
  throw new DocumentBridgeError("未找到 mnote 仓库根目录", 500, "TRANSPORT_ERROR");
}

async function readLatestMtimeMs(targetPath: string): Promise<number | null> {
  try {
    const stats = await stat(targetPath);
    if (stats.isFile()) {
      return stats.mtimeMs;
    }

    if (!stats.isDirectory()) {
      return null;
    }

    const entries = await readdir(targetPath, { withFileTypes: true });
    const nestedTimes = await Promise.all(
      entries
        .filter((entry) => !entry.name.startsWith("."))
        .map((entry) => readLatestMtimeMs(path.join(targetPath, entry.name))),
    );
    const latestChild = nestedTimes.reduce<number | null>(
      (current, next) => {
        if (typeof next !== "number" || !Number.isFinite(next)) {
          return current;
        }
        if (typeof current !== "number" || !Number.isFinite(current)) {
          return next;
        }
        return Math.max(current, next);
      },
      null,
    );
    return latestChild == null ? stats.mtimeMs : Math.max(stats.mtimeMs, latestChild);
  } catch {
    return null;
  }
}

async function readRuntimeSourceLatestMtimeMs(repoRoot: string) {
  const sourceRoots = [
    path.join(repoRoot, "rust", "Cargo.toml"),
    path.join(repoRoot, "rust", "Cargo.lock"),
    path.join(repoRoot, "rust", "crates", "bridge-runtime", "Cargo.toml"),
    path.join(repoRoot, "rust", "crates", "bridge-runtime", "src"),
    path.join(repoRoot, "rust", "crates", "storage-convex-bridge", "Cargo.toml"),
    path.join(repoRoot, "rust", "crates", "storage-convex-bridge", "src"),
    path.join(repoRoot, "rust", "crates", "core-protocol", "Cargo.toml"),
    path.join(repoRoot, "rust", "crates", "core-protocol", "src"),
  ];

  const mtimes = await Promise.all(sourceRoots.map((targetPath) => readLatestMtimeMs(targetPath)));
  return mtimes.reduce<number | null>(
    (current, next) => {
      if (typeof next !== "number" || !Number.isFinite(next)) {
        return current;
      }
      if (typeof current !== "number" || !Number.isFinite(current)) {
        return next;
      }
      return Math.max(current, next);
    },
    null,
  );
}

async function resolveRuntimeInvocation(): Promise<RuntimeInvocation> {
  const explicitBin = process.env.MNOTE_RUST_BRIDGE_BIN?.trim();
  if (explicitBin) {
    return {
      command: explicitBin,
      args: [],
    };
  }

  const repoRoot = await resolveRepoRoot();
  const builtBinary = path.join(repoRoot, "rust", "target", "debug", "bridge-runtime");
  if (await pathExists(builtBinary)) {
    const [builtBinaryMtimeMs, latestSourceMtimeMs] = await Promise.all([
      readLatestMtimeMs(builtBinary),
      readRuntimeSourceLatestMtimeMs(repoRoot),
    ]);

    if (
      shouldUseBuiltBridgeRuntimeBinary({
        builtBinaryMtimeMs,
        latestSourceMtimeMs,
      })
    ) {
      return {
        command: builtBinary,
        args: [],
      };
    }
  }

  return {
    command: "cargo",
    args: [
      "run",
      "--quiet",
      "--manifest-path",
      path.join(repoRoot, "rust", "Cargo.toml"),
      "-p",
      "bridge-runtime",
      "--",
    ],
  };
}

async function runRustRuntime(input: Record<string, unknown>): Promise<RustRuntimeResponse> {
  const invocation = await resolveRuntimeInvocation();
  const result = await new Promise<RuntimeProcessResult>((resolve, reject) => {
    const child = spawn(invocation.command, invocation.args, {
      stdio: ["pipe", "pipe", "pipe"],
      env: resolveRustRuntimeProcessEnv(),
    });

    let stdout = "";
    let stderr = "";
    let timedOut = false;
    const timeout = setTimeout(() => {
      timedOut = true;
      child.kill("SIGKILL");
    }, RUST_RUNTIME_TIMEOUT_MS);

    child.stdout.setEncoding("utf8");
    child.stderr.setEncoding("utf8");
    child.stdout.on("data", (chunk: string) => {
      stdout += chunk;
    });
    child.stderr.on("data", (chunk: string) => {
      stderr += chunk;
    });
    child.on("error", (error) => {
      clearTimeout(timeout);
      reject(error);
    });
    child.on("close", (code, signal) => {
      clearTimeout(timeout);
      if (timedOut) {
        reject(new DocumentBridgeError("Rust runtime 执行超时", 504, "TRANSPORT_ERROR"));
        return;
      }
      resolve({
        code,
        signal,
        stdout,
        stderr,
      });
    });

    child.stdin.end(JSON.stringify(input));
  }).catch((error: unknown) => {
    if (error instanceof DocumentBridgeError) {
      throw error;
    }
    throw new DocumentBridgeError(
      error instanceof Error ? `Rust runtime 启动失败: ${error.message}` : "Rust runtime 启动失败",
      500,
      "TRANSPORT_ERROR",
    );
  });

  const raw = result.stdout.trim();
  if (!raw) {
    throw new DocumentBridgeError(
      result.stderr.trim() || "Rust runtime 未返回任何结果",
      500,
      "TRANSPORT_ERROR",
    );
  }

  let parsed: RustRuntimeResponse;
  try {
    parsed = JSON.parse(raw) as RustRuntimeResponse;
  } catch (error) {
    throw new DocumentBridgeError(
      `Rust runtime 返回了非法 JSON: ${error instanceof Error ? error.message : "unknown"}`,
      500,
      "TRANSPORT_ERROR",
      {
        stdout: raw,
        stderr: result.stderr.trim() || null,
      },
    );
  }

  if (result.code !== 0 || !parsed.ok) {
    if (!parsed.ok) {
      throw toDocumentBridgeError("error" in parsed ? parsed.error : { kind: "transport", message: "Rust runtime 执行失败" });
    }
    throw new DocumentBridgeError(
      result.stderr.trim() ||
        `Rust runtime 执行失败(code=${String(result.code)}, signal=${String(result.signal)})`,
      500,
      "TRANSPORT_ERROR",
    );
  }

  return parsed;
}

function toDocumentBridgeError(error: RustRuntimeErrorPayload) {
  switch (error.kind) {
    case "validation":
      return new DocumentBridgeError(error.message, 400, "VALIDATION_ERROR");
    case "unauthorized":
      return new DocumentBridgeError(error.message, 401, "UNAUTHORIZED");
    case "not_found":
      return new DocumentBridgeError(error.message, 404, "NOT_FOUND");
    case "conflict":
      return new DocumentBridgeError(error.message, 409, "REJECTED");
    case "rejected":
      return new DocumentBridgeError(error.message, 409, "REJECTED");
    case "transport":
    default:
      return new DocumentBridgeError(error.message, 500, "TRANSPORT_ERROR");
  }
}

function assertObjectArgs(argsJson: Record<string, unknown>) {
  if (!argsJson || typeof argsJson !== "object" || Array.isArray(argsJson)) {
    throw new DocumentBridgeError("Rust runtime 返回了非法 transport args", 500, "TRANSPORT_ERROR");
  }
  return argsJson;
}

function assertToolPlan(plan: RustBridgeQueryPlan | RustBridgeCommandPlan | RustBridgeToolPlan): RustBridgeToolPlan {
  if (plan.kind !== "tool") {
    throw new DocumentBridgeError("Rust runtime 返回了错误的 tool plan", 500, "TRANSPORT_ERROR");
  }
  return {
    ...plan,
    argsJson: assertObjectArgs(plan.argsJson),
    target:
      plan.target && typeof plan.target === "object" && !Array.isArray(plan.target)
        ? (plan.target as Record<string, unknown>)
        : null,
    steps: Array.isArray(plan.steps)
      ? plan.steps.map((step) => ({
          kind: String(step.kind ?? ""),
          name: String(step.name ?? ""),
          functionName: typeof step.functionName === "string" ? step.functionName : null,
          description: String(step.description ?? ""),
          argsJson:
            step.argsJson && typeof step.argsJson === "object" && !Array.isArray(step.argsJson)
              ? (step.argsJson as Record<string, unknown>)
              : {},
        }))
      : [],
  };
}

function assertStringArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  if (typeof value !== "string" || !value.trim()) {
    throw new DocumentBridgeError(`Rust runtime 缺少 ${field}`, 500, "TRANSPORT_ERROR");
  }
  return value;
}

function readOptionalIntegerArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  if (value === null || typeof value === "undefined") {
    return null;
  }
  if (typeof value === "number" && Number.isInteger(value)) {
    return value;
  }
  throw new DocumentBridgeError(`Rust runtime 的 ${field} 非法`, 500, "TRANSPORT_ERROR");
}

function readOptionalStringArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  if (value === null || typeof value === "undefined") {
    return null;
  }
  if (typeof value === "string") {
    const trimmed = value.trim();
    return trimmed || null;
  }
  throw new DocumentBridgeError(`Rust runtime 的 ${field} 非法`, 500, "TRANSPORT_ERROR");
}

function readRequiredNumberArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  if (typeof value === "number" && Number.isFinite(value)) {
    return value;
  }
  throw new DocumentBridgeError(`Rust runtime 缺少 ${field}`, 500, "TRANSPORT_ERROR");
}

function readStringArrayArg(argsJson: Record<string, unknown>, field: string): string[] {
  const value = argsJson[field];
  if (!Array.isArray(value)) {
    throw new DocumentBridgeError(`Rust runtime 缺少 ${field}`, 500, "TRANSPORT_ERROR");
  }
  return value
    .map((item) => (typeof item === "string" ? item.trim() : ""))
    .filter((item) => item.length > 0);
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}

function readRecordField(source: unknown, field: string) {
  if (!isRecord(source)) {
    return null;
  }
  const value = source[field];
  return isRecord(value) ? value : null;
}

function readOptionalRecordArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  return isRecord(value) ? value : null;
}

function readRequiredRecordArg(argsJson: Record<string, unknown>, field: string) {
  const value = argsJson[field];
  if (isRecord(value)) {
    return value;
  }
  throw new DocumentBridgeError(`Rust runtime 缺少 ${field}`, 500, "TRANSPORT_ERROR");
}

function readOptionalBooleanField(source: Record<string, unknown>, field: string) {
  const value = source[field];
  return typeof value === "boolean" ? value : undefined;
}

function readOptionalNonEmptyStringField(source: Record<string, unknown>, field: string) {
  const value = source[field];
  if (typeof value !== "string") {
    return undefined;
  }
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : undefined;
}

function readNullableStringField(source: Record<string, unknown>, field: string) {
  const value = source[field];
  if (value === null) {
    return null;
  }
  if (typeof value !== "string") {
    return null;
  }
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : null;
}

function readTrimmedStringField(source: unknown, field: string) {
  if (!isRecord(source)) {
    return null;
  }
  const value = source[field];
  if (typeof value !== "string") {
    return null;
  }
  const trimmed = value.trim();
  return trimmed || null;
}

function readOptionalParentIdFromResult(result: unknown, fallback: unknown): string | null {
  if (isRecord(result) && "parent_id" in result) {
    return readTrimmedStringField(result, "parent_id");
  }
  if (typeof fallback === "string") {
    const trimmed = fallback.trim();
    return trimmed || null;
  }
  return null;
}

function readFiniteNumberField(source: unknown, field: string) {
  if (!isRecord(source)) {
    return null;
  }
  const value = source[field];
  return typeof value === "number" && Number.isFinite(value) ? value : null;
}

function isTreeDeltaDocument(value: unknown): value is Record<string, unknown> {
  return (
    isRecord(value) &&
    typeof value.id === "string" &&
    typeof value.workspace_id === "string" &&
    typeof value.access_scope === "string" &&
    typeof value.is_template === "boolean" &&
    typeof value.created_at === "string" &&
    "title" in value &&
    "parent_id" in value &&
    "sort_order" in value &&
    "is_starred" in value &&
    "updated_at" in value
  );
}

function isTreeDeltaAsset(value: unknown): value is Record<string, unknown> {
  return (
    isRecord(value) &&
    typeof value.id === "string" &&
    typeof value.workspace_id === "string" &&
    typeof value.document_id === "string" &&
    typeof value.asset_type === "string" &&
    typeof value.created_at === "string" &&
    typeof value.updated_at === "string" &&
    "file_name" in value &&
    "file_url" in value &&
    "thumbnail_url" in value &&
    "file_size" in value &&
    "mime_type" in value
  );
}

function readStreamDeltaHint(plan: RustBridgeCommandPlan) {
  const hint = plan.argsJson.streamDeltaHint;
  if (!isRecord(hint) || hint.family !== "tree" || typeof hint.kind !== "string") {
    return null;
  }
  return {
    kind: hint.kind,
    args: isRecord(hint.args) ? hint.args : {},
  };
}

export function readRustTreeDomainEventType(plan: RustBridgeCommandPlan): string | null {
  const eventPlan = readRustTreeDomainEventPlan(plan);
  if (eventPlan) {
    return eventPlan.eventType;
  }
  const hint = plan.argsJson.domainEventHint;
  if (!isRecord(hint) || hint.family !== "tree") {
    return null;
  }
  return readTrimmedStringField(hint, "eventType");
}

export function readRustTreeDomainEventPlan(plan: RustBridgeCommandPlan): RustTreeDomainEventPlan | null {
  const eventPlan = plan.argsJson.domainEventPlan;
  return normalizeRustTreeDomainEventPlan(eventPlan);
}

export function readRustTreeDomainEventPlans(plan: RustBridgeCommandPlan): RustTreeDomainEventPlan[] {
  const eventPlans = plan.argsJson.domainEventPlans;
  if (Array.isArray(eventPlans)) {
    const normalized = eventPlans
      .map((eventPlan) => normalizeRustTreeDomainEventPlan(eventPlan))
      .filter((eventPlan): eventPlan is RustTreeDomainEventPlan => Boolean(eventPlan));
    if (normalized.length > 0) {
      return normalized;
    }
  }
  const single = readRustTreeDomainEventPlan(plan);
  return single ? [single] : [];
}

function normalizeRustTreeDomainEventPlan(eventPlan: unknown): RustTreeDomainEventPlan | null {
  if (!isRecord(eventPlan) || eventPlan.family !== "tree") {
    return null;
  }
  if (eventPlan.schema !== "mnote.tree.domain_event" || eventPlan.schemaVersion !== 1) {
    return null;
  }
  const eventType = readTrimmedStringField(eventPlan, "eventType");
  if (!eventType) {
    return null;
  }
  const streamDeltaHint = readRecordField(eventPlan, "streamDeltaHint") ?? undefined;
  const streamDelta = readRecordField(eventPlan, "streamDelta") as RustTreeStreamDelta | null;
  const payload = readRecordField(eventPlan, "payload") ?? undefined;
  return {
    family: "tree",
    schema: "mnote.tree.domain_event",
    schemaVersion: 1,
    eventType,
    ...(payload ? { payload } : {}),
    ...(streamDeltaHint ? { streamDeltaHint } : {}),
    ...(streamDelta ? { streamDelta } : {}),
  };
}

export function materializeRustTreeDomainEventPlan(input: {
  plan: RustBridgeCommandPlan;
  result: unknown;
  streamDelta?: RustTreeStreamDelta | null;
}): RustTreeDomainEventPlan | null {
  const eventPlan = readRustTreeDomainEventPlan(input.plan);
  if (!eventPlan) {
    return null;
  }
  const streamDelta =
    input.streamDelta ??
    materializeRustTreeStreamDelta({
      plan: input.plan,
      result: input.result,
    });
  return {
    ...eventPlan,
    ...(streamDelta ? { streamDelta } : {}),
  };
}

export function materializeRustTreeDomainEventPlans(input: {
  plan: RustBridgeCommandPlan;
  result: unknown;
  streamDelta?: RustTreeStreamDelta | null;
}): RustTreeDomainEventPlan[] {
  const eventPlans = readRustTreeDomainEventPlans(input.plan);
  const streamDelta =
    input.streamDelta ??
    materializeRustTreeStreamDelta({
      plan: input.plan,
      result: input.result,
    });
  return eventPlans.map((eventPlan) => ({
    ...eventPlan,
    ...(streamDelta ? { streamDelta } : {}),
  }));
}

export function materializeRustTreeStreamDelta(input: {
  plan: RustBridgeCommandPlan;
  result: unknown;
}): RustTreeStreamDelta | null {
  const hint = readStreamDeltaHint(input.plan);
  if (!hint) {
    return null;
  }

  if (hint.kind === "noop") {
    return { op: "noop" };
  }

  if (hint.kind === "resync_required") {
    const reason = readTrimmedStringField(hint.args, "reason");
    const pageId = readTrimmedStringField(hint.args, "pageId");
    const documentId = readTrimmedStringField(hint.args, "documentId");
    const blockId = readTrimmedStringField(hint.args, "blockId");
    return {
      op: "resync_required",
      ...(reason ? { reason } : {}),
      ...(pageId ? { pageId } : {}),
      ...(documentId ? { documentId } : {}),
      ...(blockId ? { blockId } : {}),
    };
  }

  if (hint.kind === "remove_document") {
    const documentId = readTrimmedStringField(hint.args, "documentId");
    return documentId ? { op: "remove_document", documentId } : null;
  }

  if (hint.kind === "upsert_document_patch") {
    const documentId = readTrimmedStringField(hint.args, "documentId");
    const patch = readRecordField(hint.args, "patch");
    if (!documentId || !patch) {
      return null;
    }
    const updatedAt = readTrimmedStringField(input.result, "updated_at");
    return {
      op: "upsert_document",
      document: {
        id: documentId,
        ...patch,
        ...(updatedAt && !("updated_at" in patch) ? { updated_at: updatedAt } : {}),
      },
    };
  }

  if (hint.kind === "document_result") {
    const documentField = readTrimmedStringField(hint.args, "documentField") ?? "document";
    const document = readRecordField(input.result, documentField);
    if (!isTreeDeltaDocument(document)) {
      return null;
    }
    return {
      op: "upsert_document",
      document,
    };
  }

  if (hint.kind === "result_document") {
    if (!isTreeDeltaDocument(input.result)) {
      return null;
    }
    return {
      op: "upsert_document",
      document: input.result,
    };
  }

  if (hint.kind === "copy_result") {
    const itemsField = readTrimmedStringField(hint.args, "itemsField") ?? "items";
    const documentField = readTrimmedStringField(hint.args, "documentField") ?? "document";
    const items = isRecord(input.result) && Array.isArray(input.result[itemsField]) ? input.result[itemsField] : [];
    const upsertDocuments = items
      .map((item) => readRecordField(item, documentField))
      .filter(isTreeDeltaDocument);
    return upsertDocuments.length > 0
      ? {
          op: "upsert_documents",
          upsertDocuments,
        }
      : null;
  }

  if (hint.kind === "asset_result") {
    const itemsField = readTrimmedStringField(hint.args, "itemsField") ?? "items";
    const items = isRecord(input.result) && Array.isArray(input.result[itemsField]) ? input.result[itemsField] : [];
    const upsertAssets = items.filter(isTreeDeltaAsset);
    return upsertAssets.length > 0
      ? {
          op: "upsert_assets",
          upsertAssets,
        }
      : null;
  }

  if (hint.kind === "move_document") {
    const documentId = readTrimmedStringField(hint.args, "documentId");
    const fallbackSortOrder = readFiniteNumberField(hint.args, "sortOrder");
    const sortOrder = readFiniteNumberField(input.result, "sort_order") ?? fallbackSortOrder;
    if (!documentId || typeof sortOrder !== "number") {
      return null;
    }
    const updatedAt = readTrimmedStringField(input.result, "updated_at");
    return {
      op: "move_document",
      documentId,
      parentId: readOptionalParentIdFromResult(input.result, hint.args.parentId),
      sortOrder,
      ...(updatedAt ? { updatedAt } : {}),
    };
  }

  return null;
}

function nowIsoForRustArtifact() {
  return new Date().toISOString();
}

export async function buildRustBridgeCommandArtifactPlan(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<unknown>;
  plan: RustBridgeCommandPlan;
  result: unknown;
  now?: string;
}): Promise<RustBridgeCommandArtifactPlan | null> {
  const response = await runRustRuntime({
    kind: "commandArtifact",
    context: input.context,
    command: {
      ...input.envelope,
      preflightData: input.envelope.preflightData ?? null,
    },
    plan: input.plan,
    result: input.result,
    now: input.now ?? nowIsoForRustArtifact(),
  });

  if (!("artifacts" in response)) {
    throw new DocumentBridgeError("Rust runtime 未返回 command artifact plan", 500, "TRANSPORT_ERROR");
  }
  return response.artifacts;
}

export async function persistRustBridgeCommandArtifacts(input: {
  client: ConvexHttpClient;
  artifacts: RustBridgeCommandArtifactPlan | null;
}): Promise<void> {
  const artifacts = input.artifacts;
  if (!artifacts) {
    return;
  }
  const bridgeLogsApi = api as typeof api & {
    bridgeLogs: {
      recordCommandLog: unknown;
      recordDomainEvent: unknown;
    };
  };
  const mutation = input.client.mutation.bind(input.client) as (
    mutationReference: unknown,
    args: Record<string, unknown>,
  ) => Promise<unknown>;

  await mutation(bridgeLogsApi.bridgeLogs.recordCommandLog, artifacts.commandLog as unknown as Record<string, unknown>);
  const domainEvents =
    artifacts.domainEvents && artifacts.domainEvents.length > 0
      ? artifacts.domainEvents
      : artifacts.domainEvent
        ? [artifacts.domainEvent]
        : [];
  for (const domainEvent of domainEvents) {
    await mutation(bridgeLogsApi.bridgeLogs.recordDomainEvent, domainEvent as unknown as Record<string, unknown>);
  }
}

export async function recordRustBridgeCommandArtifacts(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<unknown>;
  client: ConvexHttpClient;
  plan: RustBridgeCommandPlan;
  result: unknown;
  now?: string;
}): Promise<RustBridgeCommandArtifactPlan | null> {
  const artifacts = await buildRustBridgeCommandArtifactPlan({
    context: input.context,
    envelope: input.envelope,
    plan: input.plan,
    result: input.result,
    now: input.now,
  });
  await persistRustBridgeCommandArtifacts({
    client: input.client,
    artifacts,
  });
  return artifacts;
}

export async function resolveRustBridgeQueryPlan<TPayload>(input: {
  context: BridgeContext;
  envelope: QueryEnvelope<TPayload>;
}): Promise<RustBridgeQueryPlan> {
  const response = await runRustRuntime({
    kind: "query",
    context: input.context,
    query: input.envelope,
  });

  if (!("plan" in response) || response.plan.kind !== "query") {
    throw new DocumentBridgeError("Rust runtime 返回了错误的 query plan", 500, "TRANSPORT_ERROR");
  }

  return {
    ...response.plan,
    argsJson: assertObjectArgs(response.plan.argsJson),
  };
}

export async function executeRustBridgeQuery<TResult>(input: {
  context: BridgeContext;
  envelope: QueryEnvelope<unknown>;
  data?: Record<string, unknown>;
}): Promise<TResult> {
  const response = await runRustRuntime({
    kind: "query",
    context: input.context,
    query: input.envelope,
    data: input.data ?? {},
  });

  if (!("result" in response)) {
    throw new DocumentBridgeError("Rust runtime 未返回 query result", 500, "TRANSPORT_ERROR");
  }

  return response.result as TResult;
}

export async function resolveRustBridgeCommandPlan<TPayload>(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<TPayload>;
}): Promise<RustBridgeCommandPlan> {
  const response = await runRustRuntime({
    kind: "command",
    context: input.context,
    command: {
      ...input.envelope,
      preflightData: input.envelope.preflightData ?? null,
    },
  });

  if (!("plan" in response) || response.plan.kind !== "command") {
    throw new DocumentBridgeError("Rust runtime 返回了错误的 command plan", 500, "TRANSPORT_ERROR");
  }

  return {
    ...response.plan,
    argsJson: assertObjectArgs(response.plan.argsJson),
  };
}

export async function resolveRustBridgeToolPlan(input: {
  context: BridgeContext;
  toolName: string;
  invocationKind: "command" | "query" | "job";
  args: Record<string, unknown>;
  target?: BridgeTarget | null;
  reason?: string | null;
  refs?: string[];
  mode?: "plan" | "result" | "explain-plan";
}): Promise<RustBridgeToolPlan> {
  const response = await runRustRuntime({
    kind: "tool",
    context: input.context,
    tool: {
      tool: input.toolName,
      kind: input.invocationKind,
      mode: input.mode ?? "plan",
      argsJson: input.args,
      target: input.target ?? null,
      reason: input.reason ?? null,
      refs: input.refs ?? [],
    },
  });

  if (!("plan" in response)) {
    throw new DocumentBridgeError("Rust runtime 未返回 tool plan", 500, "TRANSPORT_ERROR");
  }

  if (response.plan.kind !== "tool") {
    throw new DocumentBridgeError("Rust runtime 返回了错误的 tool plan", 500, "TRANSPORT_ERROR");
  }
  return assertToolPlan(response.plan);
}

export async function executeRustBridgeTool<TResult>(input: {
  context: BridgeContext;
  toolName: string;
  invocationKind: "command" | "query" | "job";
  args: Record<string, unknown>;
  data: Record<string, unknown>;
  target?: BridgeTarget | null;
  reason?: string | null;
  refs?: string[];
  mode?: "result" | "explain-plan";
}): Promise<RustBridgeToolResult<TResult>> {
  const response = await runRustRuntime({
    kind: "tool",
    context: input.context,
    tool: {
      tool: input.toolName,
      kind: input.invocationKind,
      mode: input.mode ?? "result",
      argsJson: input.args,
      target: input.target ?? null,
      reason: input.reason ?? null,
      refs: input.refs ?? [],
    },
    data: input.data,
  });

  if (!("result" in response)) {
    throw new DocumentBridgeError("Rust runtime 未返回 tool result", 500, "TRANSPORT_ERROR");
  }

  const plan = await resolveRustBridgeToolPlan({
    context: input.context,
    toolName: input.toolName,
    invocationKind: input.invocationKind,
    args: input.args,
    target: input.target,
    reason: input.reason,
    refs: input.refs,
    mode: input.mode === "explain-plan" ? "explain-plan" : "plan",
  });

  return {
    plan,
    result: response.result as TResult,
  };
}

export async function executeRustBridgeQueryTransport<TResult>(input: {
  client: ConvexHttpClient;
  plan: RustBridgeQueryPlan;
}): Promise<TResult> {
  const bridgeLogsApi = api as any;
  const query = input.client.query.bind(input.client) as (
    queryReference: unknown,
    args: Record<string, unknown>,
  ) => Promise<TResult>;

  switch (input.plan.functionName) {
    case "documents:getContent":
      return query(api.documents.getContent, {
        id: assertStringArg(input.plan.argsJson, "id"),
      });
    case "mindmaps:get":
      return query(api.mindmaps.get, {
        docId: assertStringArg(input.plan.argsJson, "docId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
      });
    case "mindmaps:getProjection": {
      const documentId = assertStringArg(input.plan.argsJson, "docId");
      const mindmapId = assertStringArg(input.plan.argsJson, "mindmapId");
      // compat_blob_read：当前 transport 仍从 Convex blob substrate 取数，再包装为 Rust projection 合同。
      const result = await query(api.mindmaps.get, {
        docId: documentId,
        mindmapId,
      });
      const projectionInput = {
        documentId,
        mindmapId,
        data: (result as { data?: unknown } | null)?.data,
        source: "rust-kernel",
        owner: "rust-kernel",
        meta: {
          requestId: input.plan.requestId,
          traceId: input.plan.traceId,
          workspaceId: input.plan.workspaceId,
          documentId,
          pageId: documentId,
          mindmapId,
          attachmentId: mindmapId,
          updatedAt:
            (result as { meta?: { updated_at?: string | null } | null } | null)?.meta?.updated_at ??
            null,
        },
      };
      if (input.plan.queryName === "mindmap.simple_mind_map_scene.get") {
        return buildMindmapSimpleMindMapScene(projectionInput) as TResult;
      }
      return buildMindmapProjection(projectionInput) as TResult;
    }
    case "mindmaps:getEditorScene": {
      const documentId = assertStringArg(input.plan.argsJson, "docId");
      const mindmapId = assertStringArg(input.plan.argsJson, "mindmapId");
      // compat_blob_read：editor scene 由同一 Convex blob substrate 构建，但对外暴露 Rust scene 合同。
      const result = await query(api.mindmaps.get, {
        docId: documentId,
        mindmapId,
      });
      return buildMindmapEditorScene({
        documentId,
        mindmapId,
        rootNodeId: readOptionalStringArg(input.plan.argsJson, "rootNodeId"),
        data: (result as { data?: unknown } | null)?.data,
        source: "rust-kernel",
        owner: "rust-kernel",
        meta: {
          requestId: input.plan.requestId,
          traceId: input.plan.traceId,
          workspaceId: input.plan.workspaceId,
          documentId,
          pageId: documentId,
          mindmapId,
          attachmentId: mindmapId,
          updatedAt:
            (result as { meta?: { updated_at?: string | null } | null } | null)?.meta?.updated_at ??
            null,
        },
      }) as TResult;
    }
    case "sidebar:datasetList":
      return query(api.sidebar.datasetList, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
      });
    case "blocks:getById":
      return query(api.blocks.getById, {
        userId: assertStringArg(input.plan.argsJson, "userId"),
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        blockId: assertStringArg(input.plan.argsJson, "blockId"),
      });
    case "bridgeLogs:listByRequest":
      return query(bridgeLogsApi.bridgeLogs.listByRequest, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        requestId: assertStringArg(input.plan.argsJson, "requestId"),
      });
    case "bridgeLogs:listByTrace":
      return query(bridgeLogsApi.bridgeLogs.listByTrace, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        traceId: assertStringArg(input.plan.argsJson, "traceId"),
      });
    case "bridgeLogs:listByCommand":
      return query(bridgeLogsApi.bridgeLogs.listByCommand, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        commandId: assertStringArg(input.plan.argsJson, "commandId"),
      });
    case "bridgeLogs:listWorkspaceOverview":
      return query(bridgeLogsApi.bridgeLogs.listWorkspaceOverview, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        limit:
          typeof input.plan.argsJson.limit === "number" && Number.isFinite(input.plan.argsJson.limit)
            ? input.plan.argsJson.limit
            : undefined,
        cursor: readOptionalStringArg(input.plan.argsJson, "cursor"),
        commandStatus: readOptionalStringArg(input.plan.argsJson, "commandStatus"),
        eventStatus: readOptionalStringArg(input.plan.argsJson, "eventStatus"),
        targetPageId: readOptionalStringArg(input.plan.argsJson, "targetPageId"),
        targetBlockId: readOptionalStringArg(input.plan.argsJson, "targetBlockId"),
        aggregateType: readOptionalStringArg(input.plan.argsJson, "aggregateType"),
        aggregateId: readOptionalStringArg(input.plan.argsJson, "aggregateId"),
      });
    default:
      throw new DocumentBridgeError(
        `未注册的 Rust query transport: ${input.plan.functionName}`,
        500,
        "TRANSPORT_ERROR",
      );
  }
}

export async function executeRustBridgeMutationTransport<TResult>(input: {
  client: ConvexHttpClient;
  plan: RustBridgeCommandPlan;
}): Promise<TResult> {
  const mutation = input.client.mutation.bind(input.client) as (
    mutationReference: unknown,
    args: Record<string, unknown>,
  ) => Promise<TResult>;
  const runtimeApi = api as typeof api & {
    mediaAssets: {
      batchCopy: unknown;
      batchMove: unknown;
    };
    mindmaps: {
      applyCommand: unknown;
    };
  };

  switch (input.plan.functionName) {
    case "documents:createWithParentReference":
      return mutation(api.documents.create, {
        id: assertStringArg(input.plan.argsJson, "id"),
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
        parentId: readOptionalStringArg(input.plan.argsJson, "parentId"),
        title: assertStringArg(input.plan.argsJson, "title"),
        accessScope: assertStringArg(input.plan.argsJson, "accessScope"),
        content: input.plan.argsJson.content,
      });
    case "documents:move":
      return mutation(api.documents.move, {
        id: assertStringArg(input.plan.argsJson, "id"),
        parentId: readOptionalStringArg(input.plan.argsJson, "parentId"),
        sortOrder: readRequiredNumberArg(input.plan.argsJson, "sortOrder"),
        treeWriteOperation: readRequiredRecordArg(input.plan.argsJson, "treeWriteOperation"),
      });
    case "documents:softDelete":
      return mutation(api.documents.softDelete, {
        id: assertStringArg(input.plan.argsJson, "id"),
      });
    case "documents:restore":
      return mutation(api.documents.restore, {
        id: assertStringArg(input.plan.argsJson, "id"),
      });
    case "documents:duplicateWithMindmaps":
      return mutation(api.documents.duplicate, {
        sourceId: assertStringArg(input.plan.argsJson, "sourceId"),
        newId: assertStringArg(input.plan.argsJson, "newId"),
        title: readOptionalStringArg(input.plan.argsJson, "title"),
      });
    case "documents:updateStats":
      return mutation(api.documents.updateStats, {
        id: assertStringArg(input.plan.argsJson, "id"),
        wordCount: readRequiredNumberArg(input.plan.argsJson, "wordCount"),
        characterCount: readRequiredNumberArg(input.plan.argsJson, "characterCount"),
        blockCount: readRequiredNumberArg(input.plan.argsJson, "blockCount"),
        todoTotal: readRequiredNumberArg(input.plan.argsJson, "todoTotal"),
        todoDone: readRequiredNumberArg(input.plan.argsJson, "todoDone"),
      });
    case "documents:updateOptions": {
      const options = readOptionalRecordArg(input.plan.argsJson, "options");
      if (!options) {
        throw new DocumentBridgeError("Rust runtime 缺少 options", 500, "TRANSPORT_ERROR");
      }
      return mutation(api.documents.updateOptions, {
        id: assertStringArg(input.plan.argsJson, "id"),
        options: {
          wideLayout: readOptionalBooleanField(options, "wideLayout"),
          smallText: readOptionalBooleanField(options, "smallText"),
          showHeadingNumbers: readOptionalBooleanField(options, "showHeadingNumbers"),
          showToc: readOptionalBooleanField(options, "showToc"),
          showStructure: readOptionalBooleanField(options, "showStructure"),
          protectEditing: readOptionalBooleanField(options, "protectEditing"),
          showWordCount: readOptionalBooleanField(options, "showWordCount"),
          collapseBacklinks: readOptionalBooleanField(options, "collapseBacklinks"),
          pageFont: readOptionalNonEmptyStringField(options, "pageFont"),
          layoutDensity: readOptionalNonEmptyStringField(options, "layoutDensity"),
          hideChildPages: readOptionalBooleanField(options, "hideChildPages"),
          showBlockRefCount: readOptionalBooleanField(options, "showBlockRefCount"),
          embedDefaultBlockId: readNullableStringField(options, "embedDefaultBlockId"),
        },
      });
    }
    case "documents:copyTree": {
      const rawItems = input.plan.argsJson.items;
      const items = Array.isArray(rawItems)
        ? rawItems
            .filter((item): item is Record<string, unknown> => Boolean(item) && typeof item === "object" && !Array.isArray(item))
            .map((item) => ({
              documentId: assertStringArg(item, "documentId"),
              recursive: Boolean(item.recursive),
            }))
        : [];
      return mutation(api.documents.copyTree, {
        items,
        targetParentId: readOptionalStringArg(input.plan.argsJson, "targetParentId"),
      });
    }
    case "mediaAssets:batchCopy":
    case "mediaAssets:batchMove":
      return mutation(
        input.plan.functionName === "mediaAssets:batchCopy"
          ? runtimeApi.mediaAssets.batchCopy
          : runtimeApi.mediaAssets.batchMove,
        {
          userId: input.plan.actorId,
          assetIds: readStringArrayArg(input.plan.argsJson, "assetIds"),
          targetDocumentId: assertStringArg(input.plan.argsJson, "targetDocumentId"),
          targetSubPath: readOptionalStringArg(input.plan.argsJson, "targetSubPath"),
          resourceTransferPlan: readOptionalRecordArg(
            input.plan.argsJson,
            "resourceTransferPlan",
          ),
        },
      );
    case "mediaAssets:replaceStorageFromUpload":
      return mutation(api.mediaAssets.replaceStorageFromUpload, {
        userId: assertStringArg(input.plan.argsJson, "userId"),
        id: assertStringArg(input.plan.argsJson, "id"),
        storageId: assertStringArg(input.plan.argsJson, "storageId") as Id<"_storage">,
      });
    case "documents:setTemplate":
      return mutation(api.documents.setTemplate, {
        id: assertStringArg(input.plan.argsJson, "id"),
        isTemplate: Boolean(input.plan.argsJson.isTemplate),
      });
    case "documents:emptyTrashByWorkspace":
      return mutation(api.documents.emptyTrashByWorkspace, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
      });
    case "documents:purge":
      return mutation(api.documents.purge, {
        id: assertStringArg(input.plan.argsJson, "id"),
      });
    case "documents:updateTitle":
      return mutation(api.documents.updateTitle, {
        id: assertStringArg(input.plan.argsJson, "id"),
        title: assertStringArg(input.plan.argsJson, "title"),
      });
    case "documents:updateContent":
      return mutation(api.documents.updateContent, {
        id: assertStringArg(input.plan.argsJson, "id"),
        content: input.plan.argsJson.content,
        expectedRevision: readOptionalIntegerArg(input.plan.argsJson, "expectedRevision"),
        conflictDetectionKey: readOptionalStringArg(input.plan.argsJson, "conflictDetectionKey"),
      });
    case "mindmaps:put":
      // compat_blob_write：整棵 put 仅保留给导入、恢复和历史调用，不作为 Phase 6 编辑主写链。
      return mutation(api.mindmaps.put, {
        docId: assertStringArg(input.plan.argsJson, "docId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
        data: input.plan.argsJson.data,
        createOnly:
          typeof input.plan.argsJson.createOnly === "boolean"
            ? input.plan.argsJson.createOnly
            : undefined,
      });
    case "mindmaps:applyCommand":
      // compat_blob_write：命令 facade 已是主写入口，但本阶段底层仍暂写 Convex blob substrate。
      return mutation(runtimeApi.mindmaps.applyCommand, {
        docId:
          readOptionalStringArg(input.plan.argsJson, "docId") ??
          assertStringArg(input.plan.argsJson, "documentId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
        commands: Array.isArray(input.plan.argsJson.commands) ? input.plan.argsJson.commands : [],
      });
    case "mindmaps:softDelete":
      return mutation(api.mindmaps.softDelete, {
        docId: assertStringArg(input.plan.argsJson, "docId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
      });
    case "mindmaps:restore":
      return mutation(api.mindmaps.restore, {
        docId: assertStringArg(input.plan.argsJson, "docId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
      });
    case "mindmaps:purge":
      return mutation(api.mindmaps.purge, {
        docId: assertStringArg(input.plan.argsJson, "docId"),
        mindmapId: assertStringArg(input.plan.argsJson, "mindmapId"),
      });
    case "mindmaps:emptyTrashByWorkspace":
      return mutation(api.mindmaps.emptyTrashByWorkspace, {
        workspaceId: assertStringArg(input.plan.argsJson, "workspaceId"),
      });
    default:
      throw new DocumentBridgeError(
        `未注册的 Rust mutation transport: ${input.plan.functionName}`,
        500,
        "TRANSPORT_ERROR",
      );
  }
}
