11import { NextResponse } from 'next/server'
22import Stripe from 'stripe'
33import { sanityWriteClient } from '@/lib/sanity-write-client'
4+ import { bridgeSponsorLeadToSponsor } from '@/lib/sponsor/sponsor-bridge'
45
56/**
67 * Stripe webhook handler for sponsor invoices.
@@ -69,6 +70,12 @@ export async function POST(request: Request) {
6970 break
7071 }
7172
73+ // Idempotency guard — skip if already paid (Stripe retries on 5xx)
74+ if ( lead . status === 'paid' ) {
75+ console . log ( '[SPONSOR] Lead already paid, skipping (idempotent):' , lead . _id )
76+ break
77+ }
78+
7279 // Update status to 'paid'
7380 await sanityWriteClient
7481 . patch ( lead . _id )
@@ -80,9 +87,18 @@ export async function POST(request: Request) {
8087
8188 console . log ( '[SPONSOR] Updated sponsorLead to paid:' , lead . _id )
8289
90+ // Bridge: create/link sponsor doc for content attribution
91+ try {
92+ await bridgeSponsorLeadToSponsor ( lead . _id )
93+ console . log ( '[SPONSOR] Sponsor bridge completed for lead:' , lead . _id )
94+ } catch ( bridgeError ) {
95+ // Non-fatal — don't fail the webhook if bridge fails
96+ console . error ( '[SPONSOR] Sponsor bridge failed (non-fatal):' , bridgeError )
97+ }
98+
8399 // Find next available automatedVideo (status script_ready or later, no sponsorSlot assigned)
84100 const availableVideo = await sanityWriteClient . fetch (
85- `*[_type == "automatedVideo" && status in ["script_ready", "media_ready", "ready_to_publish"] && !defined(bookedSlot)][0]{
101+ `*[_type == "automatedVideo" && status in ["script_ready", "media_ready", "ready_to_publish"] && !defined(bookedSlot)] | order(_createdAt asc) [0]{
86102 _id,
87103 title,
88104 status
0 commit comments