import { api } from "@/lib/convex/api";
import { getAuthedConvexClient } from "@/lib/convex/route";
import {
  buildDocumentBridgeContext,
  buildDocumentCommandEnvelope,
  buildDocumentQueryEnvelope,
  documentBridgeErrorResponse,
  type BridgeContext,
} from "@/lib/documents/bridge";
import {
  recordBridgeCommandArtifacts,
  recordBridgeCommandFailureArtifacts,
} from "@/lib/documents/bridge-log";
import {
  executeRustBridgeMutationTransport,
  executeRustBridgeQueryTransport,
  resolveRustBridgeCommandPlan,
  resolveRustBridgeQueryPlan,
} from "@/lib/documents/rust-runtime";
import { extractBlocksFromContent } from "@/lib/document-content";

type BlockLike = {
  id: string;
  type?: string;
  props?: Record<string, unknown>;
  content?: unknown;
  children?: BlockLike[];
};

function cloneBlock(block: BlockLike): BlockLike {
  return {
    ...block,
    props: block.props ? { ...block.props } : undefined,
    content: Array.isArray(block.content) ? [...block.content] : block.content,
    children: Array.isArray(block.children) ? block.children.map((item) => cloneBlock(item)) : block.children,
  };
}

function findBlockInTree(
  blocks: BlockLike[],
  blockId: string,
): { block: BlockLike; parent: BlockLike | null; index: number } | null {
  const stack: Array<{ list: BlockLike[]; parent: BlockLike | null }> = [{ list: blocks, parent: null }];
  while (stack.length > 0) {
    const current = stack.pop();
    if (!current) continue;
    for (let i = 0; i < current.list.length; i += 1) {
      const block = current.list[i]!;
      if (block.id === blockId) {
        return { block, parent: current.parent, index: i };
      }
      if (Array.isArray(block.children) && block.children.length > 0) {
        stack.push({ list: block.children, parent: block });
      }
    }
  }
  return null;
}

function removeBlockSubtree(blocks: BlockLike[], blockId: string) {
  const nextTop = blocks.map((item) => cloneBlock(item));
  const hit = findBlockInTree(nextTop, blockId);
  if (!hit) {
    return { removed: null as BlockLike | null, nextBlocks: nextTop };
  }
  if (hit.parent) {
    const nextChildren = Array.isArray(hit.parent.children) ? hit.parent.children.map((item) => cloneBlock(item)) : [];
    const removed = nextChildren.splice(hit.index, 1)[0] ?? null;
    hit.parent.children = nextChildren;
    return { removed, nextBlocks: nextTop };
  }
  const removed = nextTop.splice(hit.index, 1)[0] ?? null;
  return { removed, nextBlocks: nextTop };
}

function replaceBlockInTree(blocks: BlockLike[], blockId: string, nextBlock: unknown) {
  const nextTop = blocks.map((item) => cloneBlock(item));
  const hit = findBlockInTree(nextTop, blockId);
  if (!hit || !nextBlock || typeof nextBlock !== "object" || Array.isArray(nextBlock)) {
    return { ok: false, nextBlocks: nextTop };
  }
  const normalized = cloneBlock({ ...(nextBlock as BlockLike), id: blockId });
  if (hit.parent) {
    const nextChildren = Array.isArray(hit.parent.children) ? hit.parent.children.map((item) => cloneBlock(item)) : [];
    nextChildren[hit.index] = normalized;
    hit.parent.children = nextChildren;
    return { ok: true, nextBlocks: nextTop };
  }
  nextTop[hit.index] = normalized;
  return { ok: true, nextBlocks: nextTop };
}

async function buildBridgeContext(request: Request, workspaceId: string | null): Promise<BridgeContext> {
  return await buildDocumentBridgeContext({ request, workspaceId });
}

export async function executeBlockGetBridgeQuery(input: {
  request: Request;
  sourceDocumentId: string;
  blockId: string;
}) {
  const context = await buildBridgeContext(input.request, null);
  const envelope = buildDocumentQueryEnvelope({
    name: "blocks.get",
    payload: {
      sourceDocumentId: input.sourceDocumentId,
      blockId: input.blockId,
    },
  });
  const plan = await resolveRustBridgeQueryPlan({ context, envelope });
  const { client } = await getAuthedConvexClient();
  const doc = await executeRustBridgeQueryTransport<{ content?: unknown } | null>({
    client,
    plan,
  });
  if (!doc) {
    throw new Error("页面不存在或无权限");
  }
  const blocks = extractBlocksFromContent(doc.content) as BlockLike[];
  const hit = findBlockInTree(blocks, input.blockId);
  if (!hit) {
    throw new Error("块不存在或无权限");
  }
  return {
    requestId: context.requestId,
    traceId: context.traceId,
    queryName: envelope.name,
    result: { block: hit.block },
  };
}

export async function executeBlockPatchBridgeCommand(input: {
  request: Request;
  sourceDocumentId: string;
  workspaceId: string | null;
  blockId: string;
  nextBlock: unknown;
}) {
  const context = await buildBridgeContext(input.request, input.workspaceId);
  const envelope = buildDocumentCommandEnvelope({
    name: "blocks.patch",
    payload: {
      documentId: input.sourceDocumentId,
      workspaceId: input.workspaceId,
      blockId: input.blockId,
      nextBlock: input.nextBlock,
    },
    context,
    target: {
      workspaceId: input.workspaceId,
      pageId: input.sourceDocumentId,
      blockId: input.blockId,
    },
  });
  const plan = await resolveRustBridgeCommandPlan({ context, envelope });
  const { client } = await getAuthedConvexClient();
  const doc = await client.query(api.documents.getContent, { id: input.sourceDocumentId });
  if (!doc) {
    throw new Error("页面不存在或无权限");
  }
  const blocks = extractBlocksFromContent(doc.content) as BlockLike[];
  const replaced = replaceBlockInTree(blocks, input.blockId, input.nextBlock);
  if (!replaced.ok) {
    throw new Error("块不存在或无权限");
  }
  try {
    await executeRustBridgeMutationTransport({
      client,
      plan,
    });
    await recordBridgeCommandArtifacts({ context, envelope });
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      client,
      context,
      envelope,
      error,
    });
    throw error;
  }
  return {
    requestId: context.requestId,
    traceId: context.traceId,
    commandId: envelope.commandId,
    commandName: envelope.name,
    result: { ok: true as const },
  };
}

export async function executeBlockMoveBridgeCommand(input: {
  request: Request;
  sourceDocumentId: string;
  targetDocumentId: string;
  blockId: string;
}) {
  const { client } = await getAuthedConvexClient();
  const source = await client.query(api.documents.getContent, { id: input.sourceDocumentId });
  if (!source) throw new Error("源页面不存在或无权限");
  const target = await client.query(api.documents.getContent, { id: input.targetDocumentId });
  if (!target) throw new Error("目标页面不存在或无权限");
  const sourceBlocks = extractBlocksFromContent(source.content) as BlockLike[];
  const removedRes = removeBlockSubtree(sourceBlocks, input.blockId);
  if (!removedRes.removed) throw new Error("源块不存在或无权限");
  const context = await buildBridgeContext(input.request, null);
  const envelope = buildDocumentCommandEnvelope({
    name: "blocks.move",
    payload: {
      sourceDocumentId: input.sourceDocumentId,
      targetDocumentId: input.targetDocumentId,
      blockId: input.blockId,
    },
    context,
    target: {
      pageId: input.targetDocumentId,
      blockId: input.blockId,
    },
  });
  const plan = await resolveRustBridgeCommandPlan({ context, envelope });
  try {
    await executeRustBridgeMutationTransport({ client, plan });
    await recordBridgeCommandArtifacts({ context, envelope });
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      client,
      context,
      envelope,
      error,
    });
    throw error;
  }
  return {
    requestId: context.requestId,
    traceId: context.traceId,
    commandId: envelope.commandId,
    commandName: envelope.name,
    result: { ok: true as const },
  };
}

export async function executeBlockEmbedBridgeCommand(input: {
  request: Request;
  sourceDocumentId: string;
  targetDocumentId: string;
  blockId: string;
}) {
  const { client } = await getAuthedConvexClient();
  const source = await client.query(api.documents.getContent, { id: input.sourceDocumentId });
  if (!source) throw new Error("源页面不存在或无权限");
  const target = await client.query(api.documents.getContent, { id: input.targetDocumentId });
  if (!target) throw new Error("目标页面不存在或无权限");
  const targetMeta = await client.query(api.documents.getMeta, { id: input.targetDocumentId });
  const sourceBlocks = extractBlocksFromContent(source.content) as BlockLike[];
  const hit = findBlockInTree(sourceBlocks, input.blockId);
  if (!hit) throw new Error("源块不存在或无权限");
  const anchorId = (targetMeta as { embed_default_block_id?: string | null } | null)?.embed_default_block_id ?? null;
  const anchorIndex =
    typeof anchorId === "string" && anchorId.trim()
      ? extractBlocksFromContent(target.content).findIndex((block) => String((block as BlockLike).id ?? "") === anchorId)
      : -1;
  const targetBlocks = extractBlocksFromContent(target.content) as BlockLike[];
  void targetBlocks;
  void anchorIndex;
  const context = await buildBridgeContext(input.request, null);
  const envelope = buildDocumentCommandEnvelope({
    name: "blocks.embed",
    payload: {
      sourceDocumentId: input.sourceDocumentId,
      targetDocumentId: input.targetDocumentId,
      blockId: input.blockId,
    },
    context,
    target: {
      pageId: input.targetDocumentId,
      blockId: input.blockId,
    },
  });
  const plan = await resolveRustBridgeCommandPlan({ context, envelope });
  try {
    await executeRustBridgeMutationTransport({ client, plan });
    await recordBridgeCommandArtifacts({ context, envelope });
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      client,
      context,
      envelope,
      error,
    });
    throw error;
  }
  return {
    requestId: context.requestId,
    traceId: context.traceId,
    commandId: envelope.commandId,
    commandName: envelope.name,
    result: { ok: true as const },
  };
}

export function handleBlockBridgeError(error: unknown) {
  return documentBridgeErrorResponse(error);
}
