import { randomUUID } from "node:crypto";
import { NextResponse } from "next/server";
import type { ConvexHttpClient } from "convex/browser";
import { api } from "@/lib/convex/api";
import { getAuthedConvexClient } from "@/lib/convex/route";
import {
  assertDocumentId,
  buildDocumentBridgeContext,
  buildDocumentCommandEnvelope,
  documentBridgeErrorResponse,
  type BridgeContext,
  type CommandEnvelope,
} from "@/lib/documents/bridge";
import {
  recordBridgeCommandArtifacts,
  recordBridgeCommandFailureArtifacts,
} from "@/lib/documents/bridge-log";
import { composeContentWithBlocks, extractBlocksFromContent } from "@/lib/document-content";
import {
  executeRustBridgeMutationTransport,
  resolveRustBridgeCommandPlan,
} from "@/lib/documents/rust-runtime";
import { buildDocumentSavePayload } from "@/lib/documents/save-contract";
import type { Json } from "@/types/supabase";

export type DocumentCreatePayload = {
  documentId: string;
  workspaceId: string;
  parentId: string | null;
  title: string;
  accessScope: "private" | "shared" | "public";
  content: unknown;
};

export type DocumentMovePayload = {
  documentId: string;
  workspaceId: string | null;
  parentId: string | null;
  sortOrder: number;
};

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

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

export type DocumentDuplicatePayload = {
  sourceDocumentId: string;
  newDocumentId: string;
  workspaceId: string | null;
  title: string | null;
};

export type DocumentCopyTreePayload = {
  workspaceId: string | null;
  targetParentId: string | null;
  items: Array<{
    documentId: string;
    recursive: boolean;
  }>;
};

export type DocumentTemplatePayload = {
  documentId: string;
  isTemplate: boolean;
};

export type DocumentEmptyTrashPayload = {
  workspaceId: string;
};

export type DocumentPurgePayload = {
  documentId: string;
};

export type DocumentEmbedPayload = {
  documentId: string;
  workspaceId: string | null;
  revision: number | null;
  content: Json;
  conflictDetectionKey: string | null;
  snapshotCapturedAt: string | null;
  blockCount: number | null;
  sourceDocumentId: string;
  targetDocumentId: string;
  anchorBlockId: string | null;
};

export type PageCommandExecutionResult<TResult> = {
  requestId: string;
  traceId: string;
  commandId: string;
  commandName: string;
  result: TResult;
};

function trimOrNull(value: unknown): string | null {
  if (typeof value !== "string") return null;
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : null;
}

function normalizeTitle(title: string | null | undefined): string {
  const safe = typeof title === "string" ? title.trim() : "";
  return safe.length > 0 ? safe : "无标题";
}

function safeRandomId(): string {
  return typeof crypto.randomUUID === "function" ? crypto.randomUUID() : randomUUID();
}

function normalizeWorkspaceId(value: string | null | undefined): string | null {
  return trimOrNull(value);
}

async function withAuthedClient() {
  const { auth, client } = await getAuthedConvexClient();
  return { auth, client };
}

async function buildRuntimeContext(request: Request, workspaceId: string | null) {
  return buildDocumentBridgeContext({
    request,
    workspaceId,
  });
}

export async function executePageLifecycleBridgeCommand<TPayload, TResult>(input: {
  context: BridgeContext;
  envelope: CommandEnvelope<TPayload>;
  client?: ConvexHttpClient;
}): Promise<PageCommandExecutionResult<TResult>> {
  const client = input.client ?? (await getAuthedConvexClient()).client;
  let result;
  try {
    const plan = await resolveRustBridgeCommandPlan({
      context: input.context,
      envelope: input.envelope,
    });
    result = await executeRustBridgeMutationTransport<TResult>({
      client,
      plan,
    });

    await recordBridgeCommandArtifacts({
      context: input.context,
      envelope: input.envelope,
      client,
    });
  } catch (error) {
    await recordBridgeCommandFailureArtifacts({
      context: input.context,
      envelope: input.envelope,
      client,
      error,
    });
    throw error;
  }

  return {
    requestId: input.context.requestId,
    traceId: input.context.traceId,
    commandId: input.envelope.commandId,
    commandName: input.envelope.name,
    result,
  };
}

export async function executeDocumentCreateChildBridgeCommand(request: Request): Promise<NextResponse> {
  try {
    const payload = (await request.json()) as {
      parentId?: string | null;
      title?: string;
      blocks?: unknown;
    };
    if (typeof payload.parentId === "undefined") {
      return NextResponse.json({ error: "缺少 parentId" }, { status: 400 });
    }

    const { auth, client } = await withAuthedClient();
    const parentId = trimOrNull(payload.parentId);
    const workspaceBootstrap = await client.mutation(api.workspaces.ensureDefaultWorkspace, {
      fallbackName: auth.email ?? auth.name ?? "我的空间",
      workspaceIdIfCreate: safeRandomId(),
    });

    let workspaceId: string | null = null;
    let accessScope: "private" | "shared" | "public" = "private";

    if (parentId) {
      const parentDoc = await client.query(api.documents.getMeta, { id: parentId });
      if (!parentDoc) {
        return NextResponse.json({ error: "父页面不存在或无权限" }, { status: 404 });
      }
      workspaceId = normalizeWorkspaceId(parentDoc.workspace_id);
      accessScope = (parentDoc.access_scope ?? "private") as typeof accessScope;
    } else {
      workspaceId = normalizeWorkspaceId(workspaceBootstrap.activeWorkspaceId);
    }

    if (!workspaceId) {
      return NextResponse.json({ error: "缺少目标工作空间" }, { status: 400 });
    }

    const resolvedTitle = normalizeTitle(payload.title);
    const contentPayload = Array.isArray(payload.blocks) ? payload.blocks : [];
    const pageId = safeRandomId();
    const context = await buildRuntimeContext(request, workspaceId);
    const envelope = buildDocumentCommandEnvelope({
      name: "documents.create",
      payload: {
        documentId: pageId,
        workspaceId,
        parentId,
        title: resolvedTitle,
        accessScope,
        content: contentPayload,
      },
      context,
      target: {
        workspaceId,
        pageId,
      },
    });

    const created = await executePageLifecycleBridgeCommand<DocumentCreatePayload, {
      id: string;
      title?: string | null;
    }>({
      context,
      envelope,
      client,
    });

    return NextResponse.json({
      pageId: created.result.id,
      title: created.result.title ?? resolvedTitle,
      meta: {
        requestId: created.requestId,
        traceId: created.traceId,
        commandId: created.commandId,
        commandName: created.commandName,
      },
    });
  } catch (error) {
    return documentBridgeErrorResponse(error);
  }
}

export async function executeDocumentEmbedBridgeCommand(request: Request): Promise<NextResponse> {
  try {
    const { sourceId, targetId } = (await request.json()) as {
      sourceId?: string;
      targetId?: string;
    };
    const normalizedSourceId = assertDocumentId(sourceId);
    const normalizedTargetId = assertDocumentId(targetId);
    const { client } = await withAuthedClient();

    const sourceDoc = await client.query(api.documents.getMeta, { id: normalizedSourceId });
    if (!sourceDoc) {
      return NextResponse.json({ error: "原始页面不存在或无权限" }, { status: 404 });
    }

    const targetContent = await client.query(api.documents.getContent, { id: normalizedTargetId });
    if (!targetContent) {
      return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
    }
    const targetMeta = await client.query(api.documents.getMeta, { id: normalizedTargetId });

    const currentBlocks = extractBlocksFromContent(targetContent.content);
    const anchorId = trimOrNull((targetMeta as { embed_default_block_id?: string | null } | null)?.embed_default_block_id);
    const anchorIndex =
      anchorId
        ? currentBlocks.findIndex(
            (block) => typeof block === "object" && block !== null && String((block as { id?: string }).id ?? "") === anchorId,
          )
        : -1;
    const insertIndex = anchorIndex >= 0 ? anchorIndex + 1 : currentBlocks.length;

    const nextBlocks: Json[] = [
      ...currentBlocks.slice(0, insertIndex),
      {
        id: safeRandomId(),
        type: "pageReference",
        props: {
          pageId: normalizedSourceId,
          title: sourceDoc.title ?? "无标题",
        },
      },
      ...currentBlocks.slice(insertIndex),
    ];

    const payload: Json = composeContentWithBlocks(targetContent.content, nextBlocks);
    const workspaceId = normalizeWorkspaceId(sourceDoc.workspace_id) ?? normalizeWorkspaceId((targetMeta as { workspace_id?: string | null } | null)?.workspace_id);
    const context = await buildRuntimeContext(request, workspaceId);
    const embedPayload: DocumentEmbedPayload = {
      ...buildDocumentSavePayload({
        documentId: normalizedTargetId,
        workspaceId,
        revision:
          typeof targetContent.revision === "number" && Number.isInteger(targetContent.revision)
            ? targetContent.revision
            : null,
        content: payload,
        conflictDetectionKey:
          typeof targetContent.conflict_detection_key === "string"
            ? targetContent.conflict_detection_key
            : null,
        blockCount: nextBlocks.length,
      }),
      sourceDocumentId: normalizedSourceId,
      targetDocumentId: normalizedTargetId,
      anchorBlockId: anchorId,
    };
    const envelope = buildDocumentCommandEnvelope({
      name: "documents.embed",
      payload: embedPayload,
      context,
      target: {
        workspaceId,
        pageId: normalizedTargetId,
      },
    });

    const result = await executePageLifecycleBridgeCommand<DocumentEmbedPayload, {
      revision?: number | null;
      conflict_detection_key?: string | null;
    }>({
      context,
      envelope,
      client,
    });

    return NextResponse.json({
      ok: true,
      meta: {
        requestId: result.requestId,
        traceId: result.traceId,
        commandId: result.commandId,
        commandName: result.commandName,
      },
    });
  } catch (error) {
    return documentBridgeErrorResponse(error);
  }
}

export async function executeDocumentTemplateBridgeCommand(request: Request): Promise<NextResponse> {
  try {
    const payload = (await request.json()) as {
      documentId?: string;
      isTemplate?: boolean;
    };
    const normalizedDocumentId = assertDocumentId(payload.documentId);
    if (typeof payload.isTemplate !== "boolean") {
      return NextResponse.json({ error: "缺少参数" }, { status: 400 });
    }

    const { client } = await withAuthedClient();
    const sourceDoc = await client.query(api.documents.getMeta, { id: normalizedDocumentId });
    if (!sourceDoc) {
      return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
    }

    const workspaceId = normalizeWorkspaceId(sourceDoc.workspace_id);
    const context = await buildRuntimeContext(request, workspaceId);
    const envelope = buildDocumentCommandEnvelope({
      name: "documents.template",
      payload: {
        documentId: normalizedDocumentId,
        isTemplate: payload.isTemplate,
      },
      context,
      target: {
        workspaceId,
        pageId: normalizedDocumentId,
      },
    });

    const result = await executePageLifecycleBridgeCommand<DocumentTemplatePayload, {
      ok?: boolean;
      updated_at?: string | null;
    }>({
      context,
      envelope,
      client,
    });

    return NextResponse.json({
      ok: true,
      meta: {
        requestId: result.requestId,
        traceId: result.traceId,
        commandId: result.commandId,
        commandName: result.commandName,
      },
    });
  } catch (error) {
    return documentBridgeErrorResponse(error);
  }
}

export async function executeDocumentEmptyTrashBridgeCommand(request: Request): Promise<NextResponse> {
  try {
    const payload = (await request.json()) as {
      workspaceId?: string;
    };
    const workspaceId = normalizeWorkspaceId(payload.workspaceId);
    if (!workspaceId) {
      return NextResponse.json({ error: "缺少 workspaceId" }, { status: 400 });
    }

    const { client } = await withAuthedClient();
    const context = await buildRuntimeContext(request, workspaceId);
    const envelope = buildDocumentCommandEnvelope({
      name: "documents.emptyTrashByWorkspace",
      payload: {
        workspaceId,
      },
      context,
      target: {
        workspaceId,
      },
    });

    const result = await executePageLifecycleBridgeCommand<DocumentEmptyTrashPayload, {
      ok?: boolean;
      deletedCount?: number;
    }>({
      context,
      envelope,
      client,
    });

    return NextResponse.json({
      success: true,
      removed: typeof result.result?.deletedCount === "number" ? result.result.deletedCount : 0,
      meta: {
        requestId: result.requestId,
        traceId: result.traceId,
        commandId: result.commandId,
        commandName: result.commandName,
      },
    });
  } catch (error) {
    return documentBridgeErrorResponse(error);
  }
}

export async function executeDocumentPurgeBridgeCommand(request: Request): Promise<NextResponse> {
  try {
    const payload = (await request.json()) as {
      documentId?: string;
    };
    const normalizedDocumentId = assertDocumentId(payload.documentId);
    const { client } = await withAuthedClient();

    const sourceDoc = await client.query(api.documents.getMeta, { id: normalizedDocumentId });
    if (!sourceDoc) {
      return NextResponse.json({ error: "页面不存在或无权限" }, { status: 404 });
    }

    const workspaceId = normalizeWorkspaceId(sourceDoc.workspace_id);
    const context = await buildRuntimeContext(request, workspaceId);
    const envelope = buildDocumentCommandEnvelope({
      name: "documents.purge",
      payload: {
        documentId: normalizedDocumentId,
      },
      context,
      target: {
        workspaceId,
        pageId: normalizedDocumentId,
      },
    });

    const result = await executePageLifecycleBridgeCommand<DocumentPurgePayload, {
      ok?: boolean;
      purged?: boolean;
      purged_at?: string | null;
    }>({
      context,
      envelope,
      client,
    });

    return NextResponse.json({
      success: true,
      purged: result.result?.purged ?? true,
      meta: {
        requestId: result.requestId,
        traceId: result.traceId,
        commandId: result.commandId,
        commandName: result.commandName,
      },
    });
  } catch (error) {
    return documentBridgeErrorResponse(error);
  }
}
