import { NextRequest, NextResponse } from "next/server" import prisma from "@/lib/prisma" import { createRedirectFlow } from "@/lib/gocardless" import { generateReference } from "@/lib/reference" export async function POST(request: NextRequest) { try { const body = await request.json() const { amountPence, donorName, donorEmail, donorPhone, giftAid, eventId, qrSourceId } = body if (!prisma) { return NextResponse.json({ error: "Database not configured" }, { status: 503 }) } // Get event + org const event = await prisma.event.findUnique({ where: { id: eventId }, include: { organization: true }, }) if (!event) { return NextResponse.json({ error: "Event not found" }, { status: 404 }) } const org = event.organization // Generate reference let reference = "" let attempts = 0 while (attempts < 10) { reference = generateReference(org.refPrefix || "PNPL", amountPence) const exists = await prisma.pledge.findUnique({ where: { reference } }) if (!exists) break attempts++ } // Create pledge in DB const pledge = await prisma.pledge.create({ data: { reference, amountPence, currency: "GBP", rail: "gocardless", status: "new", donorName: donorName || null, donorEmail: donorEmail || null, donorPhone: donorPhone || null, giftAid: giftAid || false, eventId, qrSourceId: qrSourceId || null, organizationId: org.id, }, }) // Create reminder schedule const { calculateReminderSchedule } = await import("@/lib/reminders") const schedule = calculateReminderSchedule(new Date()) await prisma.reminder.createMany({ data: schedule.map((s) => ({ pledgeId: pledge.id, step: s.step, channel: s.channel, scheduledAt: s.scheduledAt, status: "pending", payload: { templateKey: s.templateKey, subject: s.subject }, })), }) // Track analytics await prisma.analyticsEvent.create({ data: { eventType: "pledge_completed", pledgeId: pledge.id, eventId, qrSourceId: qrSourceId || null, metadata: { amountPence, rail: "gocardless" }, }, }) // Try real GoCardless flow // GoCardless live mode requires HTTPS redirect URLs const baseUrl = process.env.BASE_URL || "http://localhost:3000" const isHttps = baseUrl.startsWith("https://") const redirectUrl = `${baseUrl}/api/gocardless/callback?pledge_id=${pledge.id}` if (!isHttps && process.env.GOCARDLESS_ENVIRONMENT === "live") { // Can't use GC live with HTTP — return simulated mode // Set BASE_URL to your HTTPS domain to enable live GoCardless console.warn("GoCardless live mode requires HTTPS BASE_URL. Falling back to simulated.") return NextResponse.json({ mode: "simulated", pledgeId: pledge.id, reference, id: pledge.id, }) } const flow = await createRedirectFlow({ description: `${event.name} — ${reference}`, reference, pledgeId: pledge.id, successRedirectUrl: redirectUrl, }) if (flow) { // Save the redirect flow ID for completion await prisma.paymentInstruction.create({ data: { pledgeId: pledge.id, bankReference: reference, bankDetails: {}, gcMandateUrl: flow.redirectUrl, }, }) return NextResponse.json({ mode: "live", pledgeId: pledge.id, reference, redirectUrl: flow.redirectUrl, redirectFlowId: flow.redirectFlowId, }) } // Fallback: no GoCardless configured — return pledge for simulated flow return NextResponse.json({ mode: "simulated", pledgeId: pledge.id, reference, id: pledge.id, }) } catch (error) { console.error("GoCardless create flow error:", error) return NextResponse.json({ error: "Internal error" }, { status: 500 }) } }