import { getAuthedConvexClient } from "@/lib/convex/route";
import {
  type CommandEnvelope,
  type BridgeContext,
} from "@/lib/documents/bridge";
import {
  recordBridgeCommandArtifacts,
  recordBridgeCommandFailureArtifacts,
} from "@/lib/documents/bridge-log";
import type { DocumentSavePayload } from "@/lib/documents/save-contract";
import { DocumentBridgeError } from "@/lib/documents/bridge";
import {
  executeRustBridgeMutationTransport,
  resolveRustBridgeCommandPlan,
} from "@/lib/documents/rust-runtime";

export type DocumentSaveExecutionResult = {
  requestId: string;
  traceId: string;
  commandId: string;
  commandName: string;
  revision: number | null;
  conflictDetectionKey: string | null;
};

export async function executeSaveBridgeCommand(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<DocumentSavePayload>;
}): Promise<DocumentSaveExecutionResult> {
  const { client } = await getAuthedConvexClient();
  const plan = await resolveRustBridgeCommandPlan({
    context: input.context,
    envelope: input.envelope,
  });

  let mutationResult;
  try {
    mutationResult = await executeRustBridgeMutationTransport<{
      revision?: number | null;
      conflict_detection_key?: string | null;
    }>({
      client,
      plan,
    });
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      client,
      context: input.context,
      envelope: input.envelope,
      error,
    });
    if (error instanceof Error && /正文(内容已变更|冲突检测失败)/.test(error.message)) {
      throw new DocumentBridgeError(error.message, 409, "REJECTED", {
        reason: "content_conflict",
        revision: input.envelope.payload.revision,
        conflictDetectionKey: input.envelope.payload.conflictDetectionKey,
      });
    }
    throw error;
  }
  await recordBridgeCommandArtifacts({
    context: input.context,
    envelope: input.envelope,
  });

  return {
    requestId: input.context.requestId,
    traceId: input.context.traceId,
    commandId: input.envelope.commandId,
    commandName: input.envelope.name,
    revision:
      typeof mutationResult?.revision === "number" && Number.isInteger(mutationResult.revision)
        ? mutationResult.revision
        : null,
    conflictDetectionKey:
      typeof mutationResult?.conflict_detection_key === "string" &&
      mutationResult.conflict_detection_key.trim()
        ? mutationResult.conflict_detection_key
        : null,
  };
}
