import { NextResponse } from "next/server";
import { isConvexEnabled } from "@/lib/convex/enabled";
import { getConvexHttpClient } from "@/lib/convex/server";
import { api } from "@/lib/convex/api";
import { resolveOnlyOfficeInternalUrl } from "@/lib/onlyoffice/internal-url";
import { prepareOnlyOfficeCallback } from "@/lib/onlyoffice/rust-adapter";
import {
  buildDocumentBridgeContextWithActor,
  buildDocumentCommandEnvelope,
} from "@/lib/documents/bridge";
import {
  executeMediaAssetWritebackBridgeCommand,
  type MediaAssetReplaceStoragePayload,
} from "@/lib/documents/media-asset-command-adapter";

export const dynamic = "force-dynamic";

const ONLYOFFICE_CALLBACK_SECRET = String(process.env.ONLYOFFICE_CALLBACK_SECRET || "").trim();

type OnlyOfficeCallbackBody = {
  status?: number;
  url?: string;
  key?: string;
};

type OnlyOfficeAssetRecord = {
  document_id?: string | null;
  workspace_id?: string | null;
  mime_type?: string | null;
};

type OnlyOfficePermission = {
  permission?: string | null;
};

const normalizeSecret = (raw: string) => {
  const trimmed = String(raw || "").trim();
  if (!trimmed) return "";
  // 兼容用户把 .env 的值写成 "xxx" / 'xxx'
  if (
    (trimmed.startsWith("\"") && trimmed.endsWith("\"") && trimmed.length >= 2) ||
    (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length >= 2)
  ) {
    return trimmed.slice(1, -1).trim();
  }
  return trimmed;
};

export async function POST(request: Request) {
  try {
    const onlyofficeInternalUrl = await resolveOnlyOfficeInternalUrl();
    const { searchParams } = new URL(request.url);
    const assetId = searchParams.get("assetId") || "";

    // 说明：ONLYOFFICE 回调由文档服务器触发，不一定携带用户态；这里提供一个可选的共享密钥校验。
    // 若未配置 ONLYOFFICE_CALLBACK_SECRET，则保持兼容不校验。
    if (ONLYOFFICE_CALLBACK_SECRET) {
      const got = normalizeSecret(searchParams.get("token") || "");
      const expected = normalizeSecret(ONLYOFFICE_CALLBACK_SECRET);
      if (!got || got !== expected) {
        return NextResponse.json({ error: 1 });
      }
    }

    const body = (await request.json().catch(() => null)) as OnlyOfficeCallbackBody | null;
    if (!body) {
      return NextResponse.json({ error: 0 });
    }

    if (!assetId) {
      return NextResponse.json({ error: 1 });
    }

    if (isConvexEnabled()) {
      // 说明：Convex 模式下，保存写回 Convex Files，并更新 media_assets.storage_id/file_url。
      // 优先使用前端在 /onlyoffice 页面透传的 userId；避免固定 dev-user 导致 workspace membership 校验失败。
      const userId =
        String(searchParams.get("userId") || "").trim() ||
        String(process.env.DEV_USER_ID || "").trim() ||
        "dev-user";
      const client = getConvexHttpClient();

      const asset = (await client.query(api.mediaAssets.getById, { userId, id: assetId })) as
        | OnlyOfficeAssetRecord
        | null;
      if (!asset) {
        return NextResponse.json({ error: 1 });
      }
      const documentId = String(asset.document_id || "").trim();
      const workspaceId = String(asset.workspace_id || "").trim() || null;
      const mimeType = String(asset.mime_type || "").trim() || "application/octet-stream";

      const prepared = await prepareOnlyOfficeCallback({
        request,
        assetId,
        documentId,
        workspaceId,
        userId,
        sessionId: "onlyoffice-callback",
        status: Number(body.status ?? -1),
        url: body.url ?? null,
        key: body.key ?? null,
        onlyofficeInternalUrl,
      });
      if (!prepared.shouldWrite) {
        return NextResponse.json({ error: 0 });
      }

      // 只读权限：不允许通过 ONLYOFFICE 回调写回
      try {
        const perm = (await client.query(api.documents.getPermissionForUser, {
          userId,
          id: documentId,
        })) as OnlyOfficePermission | null;
        if (!perm || perm.permission !== "edit") {
          return NextResponse.json({ error: 1 });
        }
      } catch {
        return NextResponse.json({ error: 1 });
      }

      const downloadUrl = String(prepared.downloadUrl || "").trim();
      if (!downloadUrl) {
        return NextResponse.json({ error: 1 });
      }
      const upstream = await fetch(downloadUrl, { method: "GET", redirect: "follow" });
      if (!upstream.ok) {
        return NextResponse.json({ error: 1 });
      }

      const buf = Buffer.from(await upstream.arrayBuffer());

      const uploadUrl = await client.mutation(api.mediaAssets.generateUploadUrl, { userId });
      if (!uploadUrl || typeof uploadUrl !== "string") {
        return NextResponse.json({ error: 1 });
      }

      const uploadRes = await fetch(uploadUrl, {
        method: "POST",
        headers: { "Content-Type": mimeType },
        body: buf,
      });

      if (!uploadRes.ok) {
        return NextResponse.json({ error: 1 });
      }

      const uploadJson = (await uploadRes.json().catch(() => null)) as { storageId?: string } | null;
      const storageId = String(uploadJson?.storageId || "");
      if (!storageId) {
        return NextResponse.json({ error: 1 });
      }

      const bridgeContext = buildDocumentBridgeContextWithActor({
        request,
        workspaceId,
        actor: {
          actorType: "service",
          actorId: userId,
          sessionId: "onlyoffice-callback",
        },
        source: {
          channel: "onlyoffice-callback",
          client: "onlyoffice-document-server",
        },
        idempotencyKey: String(prepared.idempotencyKey || assetId || "").trim() || null,
      });
      const envelope = buildDocumentCommandEnvelope({
        name: "media.assets.replace_storage",
        payload: {
          assetId,
          documentId,
          workspaceId,
          storageId,
          userId,
        } satisfies MediaAssetReplaceStoragePayload,
        context: bridgeContext,
        target: {
          workspaceId,
          pageId: documentId || null,
        },
        reason: "ONLYOFFICE 回调写回附件存储",
        refs: [`onlyoffice:asset:${assetId}`],
      });

      await executeMediaAssetWritebackBridgeCommand({
        client,
        context: bridgeContext,
        envelope,
      });

      return NextResponse.json({ error: 0 });
    }

    return NextResponse.json({ error: 1 });
  } catch (error) {
    // 说明：避免异常导致 ONLYOFFICE 重试/阻塞（例如 Convex 未部署新 mutation）。
    console.error("[onlyoffice/callback] convex writeback failed:", error);
    return NextResponse.json({ error: 1 });
  }
}
