import { prisma } from '@/lib/prisma'; import { stripe } from '@/lib/stripe'; export interface CancelSubscriptionResult { success: boolean; error?: string; } /** * Cancels an active user subscription by setting its auto-renew (cancel_at_period_end) status to true * in Stripe and synchronizing the status back into the local Prisma database. * * @param userId - Unique identifier of the user * @returns An object indicating the success or failure of the operation */ export async function cancelSubscription(userId: string): Promise { if (!userId) { return { success: false, error: 'User ID is required' }; } try { const subscription = await prisma.subscription.findUnique({ where: { userId }, }); if (!subscription) { return { success: false, error: 'No active subscription found' }; } if (subscription.stripeSubscriptionId) { // Direct call to Stripe API with period end cancellation set to true const updatedSub = await stripe.subscriptions.update(subscription.stripeSubscriptionId, { cancel_at_period_end: true, }) as any; // Local database synchronization await prisma.subscription.update({ where: { userId }, data: { cancelAtPeriodEnd: true, canceledAt: updatedSub.canceled_at ? new Date(updatedSub.canceled_at * 1000) : new Date(), currentPeriodEnd: updatedSub.current_period_end ? new Date(updatedSub.current_period_end * 1000) : subscription.currentPeriodEnd, updatedAt: new Date(), }, }); } else { // Mock mode cancel (e.g. for development / local bypass testing) await prisma.subscription.update({ where: { userId }, data: { cancelAtPeriodEnd: true, canceledAt: new Date(), updatedAt: new Date(), }, }); } return { success: true }; } catch (error: any) { console.error('[cancelSubscription] Error processing cancellation:', error); return { success: false, error: error.message || 'Failed to cancel subscription', }; } }