import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";

function timingSafeEqual(a: string, b: string): boolean {
  if (a.length !== b.length) return false;
  let result = 0;
  for (let i = 0; i < a.length; i++) {
    result |= a.charCodeAt(i) ^ b.charCodeAt(i);
  }
  return result === 0;
}

export async function POST(request: NextRequest) {
  try {
    const rawBody = await request.text();
    let body: Record<string, unknown>;
    try {
      body = JSON.parse(rawBody);
    } catch {
      return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
    }

    const eventType = (body.type as string) || "";
    console.log("[polar-webhook] Received:", JSON.stringify({ type: eventType, id: (body.data as Record<string, unknown> | undefined)?.id }));

    if (!eventType.startsWith("checkout.")) {
      return NextResponse.json({ received: true, ignored: true }, { status: 200 });
    }

    const webhookSecret = process.env.POLAR_WEBHOOK_SECRET;
    if (webhookSecret) {
      const signature = request.headers.get("polar-signature") || "";
      const encoder = new TextEncoder();
      const key = await crypto.subtle.importKey(
        "raw",
        encoder.encode(webhookSecret),
        { name: "HMAC", hash: "SHA-256" },
        false,
        ["sign"]
      );
      const expectedSignatureBytes = await crypto.subtle.sign("HMAC", key, encoder.encode(rawBody));
      const expectedSignature = Array.from(new Uint8Array(expectedSignatureBytes))
        .map(b => b.toString(16).padStart(2, "0"))
        .join("");

      if (!timingSafeEqual(signature, expectedSignature)) {
        console.warn("[polar-webhook] Invalid signature");
        return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
      }
    }

    const checkout = (body.data as Record<string, unknown>) || {};
    const metadata = (checkout.metadata as Record<string, unknown>) || {};

    if (metadata.type !== "flh_purchase") {
      return NextResponse.json({ received: true, ignored: true }, { status: 200 });
    }

    if (checkout.status !== "succeeded" && checkout.status !== "paid") {
      return NextResponse.json(
        { received: true, status: checkout.status },
        { status: 200 }
      );
    }

    const userId = metadata.user_id as string;
    const flhAmount = parseInt(metadata.flh_amount as string, 10);

    if (!userId || !flhAmount || flhAmount < 1) {
      console.error("[polar-webhook] Invalid metadata:", { userId, flhAmount });
      return NextResponse.json(
        { error: "Invalid metadata: userId and flh_amount required" },
        { status: 400 }
      );
    }

    const checkoutId = (checkout.id as string) || (body.id as string);
    if (checkoutId) {
      const existing = await prisma.xpTransaction.findFirst({
        where: {
          userId,
          reason: `flh_purchase_${checkoutId}`,
        },
      });
      if (existing) {
        console.log(`[polar-webhook] Checkout ${checkoutId} already processed, skipping`);
        return NextResponse.json({ received: true, duplicate: true }, { status: 200 });
      }
    }

    const user = await prisma.user.findUnique({ where: { id: userId } });
    if (!user) {
      console.error(`[polar-webhook] User not found: ${userId}`);
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    await prisma.user.update({
      where: { id: userId },
      data: { flhBalance: { increment: flhAmount } },
    });

    if (checkoutId) {
      await prisma.xpTransaction.create({
        data: {
          userId,
          amount: flhAmount,
          reason: `flh_purchase_${checkoutId}`,
        },
      });
    }

    console.log(`[polar-webhook] Credited ${flhAmount} FLH to user ${userId}. New balance: ${user.flhBalance + flhAmount}`);
    return NextResponse.json(
      {
        received: true,
        success: true,
        flhCredited: flhAmount,
        userId,
        newBalance: user.flhBalance + flhAmount,
      },
      { status: 200 }
    );
  } catch (error) {
    console.error("[polar-webhook] Error:", error);
    return NextResponse.json(
      { error: "Webhook processing failed" },
      { status: 500 }
    );
  }
}
