import { NextResponse } from 'next/server';
import { stripe } from '@/lib/stripe';
import { prisma } from '@/lib/prisma';
import { upsertMailingListEntry } from '@/lib/mailingList';
import { applyStockMovement } from '@/lib/stock';
import type Stripe from 'stripe';

export async function POST(req: Request) {
  const signature = req.headers.get('stripe-signature');
  const rawBody = await req.text();

  if (!process.env.STRIPE_WEBHOOK_SECRET || !signature) {
    return NextResponse.json({ error: 'Webhook not configured.' }, { status: 400 });
  }

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(rawBody, signature, process.env.STRIPE_WEBHOOK_SECRET);
  } catch (err) {
    const message = err instanceof Error ? err.message : 'Invalid signature';
    return NextResponse.json({ error: `Webhook signature verification failed: ${message}` }, { status: 400 });
  }

  if (event.type === 'checkout.session.completed') {
    const session = event.data.object as Stripe.Checkout.Session;
    const orderId = session.metadata?.orderId;

    if (orderId) {
      const shipping = (session as unknown as { shipping_details?: Stripe.Checkout.Session.ShippingDetails })
        .shipping_details;

      // Stripe retries webhooks, so the same completed event can arrive more
      // than once — remember whether this is the first PENDING→PAID flip and
      // only move stock on that one.
      const before = await prisma.order.findUnique({ where: { id: orderId } });
      const firstTimePaid = before != null && before.status !== 'PAID';

      const updated = await prisma.order.update({
        where: { id: orderId },
        data: {
          status: 'PAID',
          email: session.customer_details?.email ?? undefined,
          shippingAddress: shipping ? JSON.stringify(shipping) : undefined,
        },
      });

      if (firstTimePaid) {
        const items = await prisma.orderItem.findMany({ where: { orderId } });
        await applyStockMovement(items, -1);
      }

      if (!updated.customerId && updated.email) {
        await upsertMailingListEntry({ email: updated.email, source: 'GUEST' });
      }
    }
  }

  if (event.type === 'checkout.session.expired' || event.type === 'checkout.session.async_payment_failed') {
    const session = event.data.object as Stripe.Checkout.Session;
    const orderId = session.metadata?.orderId;
    if (orderId) {
      await prisma.order.update({ where: { id: orderId }, data: { status: 'FAILED' } });
    }
  }

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