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

export const dynamic = "force-dynamic";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: "2024-06-20" });

function mapStatus(s: string) {
  switch (s) {
    case "trialing": return "trialing";
    case "active": return "active";
    case "past_due": return "past_due";
    case "canceled": return "canceled";
    case "incomplete": return "incomplete";
    case "incomplete_expired": return "incomplete_expired";
    case "paused": return "paused";
    default: return "past_due";
  }
}

export async function POST(req: NextRequest) {
  const sig = req.headers.get("stripe-signature") || "";
  const buf = Buffer.from(await req.arrayBuffer());
  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch (err: any) {
    return new NextResponse(`Webhook Error: ${err.message}`, { status: 400 });
  }

  await prisma.paymentEvent.create({
    data: {
      provider: "stripe",
      eventType: event.type,
      providerEventId: event.id,
      payloadJson: event as any
    }
  }).catch(() => {});

  if (event.type === "customer.subscription.created" || event.type === "customer.subscription.updated") {
    const sub = event.data.object as Stripe.Subscription;
    const customerId = sub.customer as string;
    const status = mapStatus(sub.status);
    const periodEnd = new Date(sub.current_period_end * 1000);

    let userId: number | null = null;
    const existing = await prisma.subscription.findFirst({
      where: { provider: "stripe", providerCustomerId: customerId }
    });
    if (existing) {
      userId = existing.userId;
    } else {
      const cust = await stripe.customers.retrieve(customerId);
      const email = (cust as any).email as string | null;
      if (email) {
        const user = await prisma.user.findUnique({ where: { email } });
        if (user) userId = user.id;
      }
    }
    if (!userId) return NextResponse.json({ received: true });

    await prisma.subscription.upsert({
      where: { provider_providerCustomerId: { provider: "stripe", providerCustomerId: customerId } },
      update: {
        providerSubscriptionId: sub.id,
        status,
        currentPeriodStart: new Date(sub.current_period_start * 1000),
        currentPeriodEnd: periodEnd,
        cancelAt: sub.cancel_at ? new Date(sub.cancel_at * 1000) : null,
        canceledAt: sub.canceled_at ? new Date(sub.canceled_at * 1000) : null
      },
      create: {
        userId,
        provider: "stripe",
        providerCustomerId: customerId,
        providerSubscriptionId: sub.id,
        status,
        currentPeriodStart: new Date(sub.current_period_start * 1000),
        currentPeriodEnd: periodEnd
      }
    });
  }

  if (event.type === "invoice.payment_failed") {
    const inv = event.data.object as Stripe.Invoice;
    const customerId = inv.customer as string;
    await prisma.subscription.updateMany({
      where: { provider: "stripe", providerCustomerId: customerId },
      data: { status: "past_due" }
    });
  }

  return NextResponse.json({ received: true });
}
