import { NextResponse } from "next/server";
import { imageContentHash, signedTokenAssetSchema, tokenAssetUploadSchema, validatePngImage, verifySignedTokenAsset } from "@pons-agent/protocol";
import { allowedPublicAgentWallets } from "@/lib/public-agent-wallets";
import { insertTokenAsset } from "@/lib/token-assets-db";

export const dynamic = "force-dynamic";
export const runtime = "nodejs";

export async function POST(request: Request) {
  try {
    const wallets = allowedPublicAgentWallets();
    if (wallets.size === 0) {
      return NextResponse.json({ error: "Token asset publishing is not configured" }, { status: 503 });
    }

    const contentLength = Number(request.headers.get("content-length") ?? 0);
    if (contentLength > 6 * 1024 * 1024) {
      return NextResponse.json({ error: "Token asset payload exceeds 6 MiB" }, { status: 413 });
    }
    const raw = await request.json();
    if (JSON.stringify(raw).length > 6 * 1024 * 1024) {
      return NextResponse.json({ error: "Token asset payload exceeds 6 MiB" }, { status: 413 });
    }

    const generated = tokenAssetUploadSchema.safeParse(raw);
    const legacy = generated.success ? null : signedTokenAssetSchema.safeParse(raw);
    if (!generated.success && !legacy?.success) throw new Error("Invalid token asset payload");
    const asset = await verifySignedTokenAsset(generated.success ? generated.data.asset : legacy!.data);
    if (!wallets.has(asset.signer.toLowerCase())) {
      return NextResponse.json({ error: "Signer is not an allowed public Agent wallet" }, { status: 403 });
    }

    let content: Buffer | null = null;
    if (generated.success) {
      if (asset.version !== 2) throw new Error("Generated token asset metadata has the wrong version");
      content = Buffer.from(generated.data.imageBase64, "base64");
      if (content.toString("base64") !== generated.data.imageBase64) throw new Error("Image payload is not valid base64");
      const dimensions = validatePngImage(content);
      if (dimensions.width !== 1024 || dimensions.height !== 1024) throw new Error("Token logo must be 1024x1024");
      if (content.length !== asset.media.byteLength) throw new Error("Image byte length does not match signed metadata");
      if (imageContentHash(content) !== asset.media.contentHash) throw new Error("Image content does not match signed metadata");
    }

    const stored = insertTokenAsset(asset, content);
    const baseUrl = process.env.TOKEN_ASSET_PUBLIC_BASE_URL ?? new URL(request.url).origin;
    const assetUrl = new URL(`/api/token-assets/${asset.assetId}`, baseUrl).href;
    return NextResponse.json({ ...stored, assetUrl }, { status: stored.created ? 201 : 200 });
  } catch (error) {
    return NextResponse.json({
      error: error instanceof Error ? error.message : "Invalid token asset",
    }, { status: 400 });
  }
}
