import { api } from "@/lib/convex/api";
import { getAuthedConvexClient } from "@/lib/convex/route";
import {
  buildDocumentBridgeMutationRequest,
  executeDocumentBridgeMutationRequest,
  type CommandEnvelope,
  type BridgeContext,
} from "@/lib/documents/bridge";
import {
  recordBridgeCommandArtifacts,
  recordBridgeCommandFailureArtifacts,
} from "@/lib/documents/bridge-log";
import {
  executeRustBridgeMutationTransport,
  resolveRustBridgeCommandPlan,
} from "@/lib/documents/rust-runtime";
import type { PageOptionsState } from "@/types/page-options";

export type DocumentTitleUpdatePayload = {
  documentId: string;
  workspaceId: string | null;
  title: string;
};

export type DocumentStatsUpdatePayload = {
  documentId: string;
  workspaceId: string | null;
  stats: {
    wordCount: number;
    characterCount: number;
    blockCount: number;
    todoTotal: number;
    todoDone: number;
  };
};

export type DocumentOptionsUpdatePayload = {
  documentId: string;
  workspaceId: string | null;
  options: Partial<PageOptionsState>;
};

export type MetadataCommandExecutionResult = {
  requestId: string;
  traceId: string;
  commandId: string;
  commandName: string;
};

type MetadataMutationArgs = Record<string, unknown>;

type MetadataWriteAdapter<TPayload> = {
  convexMutation: unknown;
  mapConvexArgs: (payload: TPayload) => MetadataMutationArgs;
};

function mapDocumentOptionsToConvexArgs(payload: DocumentOptionsUpdatePayload) {
  return {
    id: payload.documentId,
    options: {
      wideLayout: payload.options.wideLayout,
      smallText: payload.options.smallText,
      showHeadingNumbers: payload.options.showHeadingNumbers,
      showToc: payload.options.showToc,
      showStructure: payload.options.showStructure,
      protectEditing: payload.options.protectEditing,
      showWordCount: payload.options.showWordCount,
      collapseBacklinks: payload.options.collapseBacklinks,
      pageFont: payload.options.pageFont,
      layoutDensity: payload.options.layoutDensity,
      hideChildPages: payload.options.hideChildPages,
      showBlockRefCount: payload.options.showBlockRefCount,
      embedDefaultBlockId:
        typeof payload.options.embedDefaultBlockId === "string" ? payload.options.embedDefaultBlockId : null,
    },
  };
}

const metadataWriteAdapters: Record<string, MetadataWriteAdapter<unknown>> = {
  "documents.title.update": {
    convexMutation: api.documents.updateTitle,
    mapConvexArgs: (payload: DocumentTitleUpdatePayload) => ({
      id: payload.documentId,
      title: payload.title,
    }),
  },
  "page.head.updateTitle": {
    convexMutation: api.documents.updateTitle,
    mapConvexArgs: (payload: DocumentTitleUpdatePayload) => ({
      id: payload.documentId,
      title: payload.title,
    }),
  },
  "documents.stats.update": {
    convexMutation: api.documents.updateStats,
    mapConvexArgs: (payload: DocumentStatsUpdatePayload) => ({
      id: payload.documentId,
      wordCount: payload.stats.wordCount,
      characterCount: payload.stats.characterCount,
      blockCount: payload.stats.blockCount,
      todoTotal: payload.stats.todoTotal,
      todoDone: payload.stats.todoDone,
    }),
  },
  "documents.options.update": {
    convexMutation: api.documents.updateOptions,
    mapConvexArgs: mapDocumentOptionsToConvexArgs,
  },
  "page.layout.updateOptions": {
    convexMutation: api.documents.updateOptions,
    mapConvexArgs: mapDocumentOptionsToConvexArgs,
  },
};

function getMetadataWriteAdapter<TPayload>(commandName: string): MetadataWriteAdapter<TPayload> {
  const adapter = metadataWriteAdapters[commandName];
  if (!adapter) {
    throw new Error(`未注册页面元信息命令适配器: ${commandName}`);
  }
  return adapter as MetadataWriteAdapter<TPayload>;
}

export async function executeMetadataBridgeCommand<TPayload>(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<TPayload>;
}): Promise<MetadataCommandExecutionResult> {
  const { client } = await getAuthedConvexClient();
  try {
    if (
      input.envelope.name === "documents.title.update" ||
      input.envelope.name === "page.head.updateTitle"
    ) {
      const plan = await resolveRustBridgeCommandPlan({
        context: input.context,
        envelope: input.envelope,
      });
      await executeRustBridgeMutationTransport({
        client,
        plan,
      });
    } else {
      const adapter = getMetadataWriteAdapter<TPayload>(input.envelope.name);
      const mutationRequest = buildDocumentBridgeMutationRequest({
        context: input.context,
        envelope: input.envelope,
        mapConvexArgs: adapter.mapConvexArgs,
      });

      await executeDocumentBridgeMutationRequest({
        client,
        mutation: adapter.convexMutation,
        request: mutationRequest,
      });
    }
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      context: input.context,
      envelope: input.envelope,
      client,
      error,
    });
    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,
  };
}
