import { prisma } from '@/lib/db' export const SUBSCRIPTION_LIMITS = { free: 10, premium: 999999 // Effectively unlimited } export const STRIPE_PRICES = { premium_monthly: process.env.STRIPE_PREMIUM_MONTHLY_PRICE_ID || '', premium_yearly: process.env.STRIPE_PREMIUM_YEARLY_PRICE_ID || '' } export interface ConversationLimitCheck { allowed: boolean remaining: number limit: number tier: string resetDate: Date | null } /** * Check if user can create a new conversation * Handles limit checking and automatic monthly reset */ export async function checkConversationLimit(userId: string): Promise { const user = await prisma.user.findUnique({ where: { id: userId }, select: { subscriptionTier: true, conversationCount: true, conversationLimit: true, limitResetDate: true, subscriptionStatus: true } }) if (!user) { throw new Error('User not found') } // Reset counter if period expired const now = new Date() if (user.limitResetDate && now > user.limitResetDate) { const nextReset = new Date(user.limitResetDate) nextReset.setMonth(nextReset.getMonth() + 1) await prisma.user.update({ where: { id: userId }, data: { conversationCount: 0, limitResetDate: nextReset } }) user.conversationCount = 0 } // Calculate remaining conversations const remaining = user.conversationLimit - user.conversationCount // Premium users always have access (unless subscription is past_due or cancelled) const isPremiumActive = user.subscriptionTier === 'premium' && (user.subscriptionStatus === 'active' || user.subscriptionStatus === 'trialing') const allowed = isPremiumActive || remaining > 0 return { allowed, remaining: isPremiumActive ? Infinity : Math.max(0, remaining), limit: user.conversationLimit, tier: user.subscriptionTier, resetDate: user.limitResetDate } } /** * Increment user's conversation count */ export async function incrementConversationCount(userId: string): Promise { const user = await prisma.user.findUnique({ where: { id: userId }, select: { limitResetDate: true } }) if (!user) { throw new Error('User not found') } // Set initial reset date if not set (1 month from now) const now = new Date() const limitResetDate = user.limitResetDate || new Date(now.setMonth(now.getMonth() + 1)) await prisma.user.update({ where: { id: userId }, data: { conversationCount: { increment: 1 }, limitResetDate } }) } /** * Get subscription tier from Stripe price ID */ export function getTierFromPriceId(priceId: string): string { if (priceId === STRIPE_PRICES.premium_monthly || priceId === STRIPE_PRICES.premium_yearly) { return 'premium' } return 'free' } /** * Get billing interval from Stripe price ID */ export function getIntervalFromPriceId(priceId: string): string { if (priceId === STRIPE_PRICES.premium_yearly) return 'year' return 'month' } /** * Get conversation limit for a tier */ export function getLimitForTier(tier: string): number { return SUBSCRIPTION_LIMITS[tier as keyof typeof SUBSCRIPTION_LIMITS] || SUBSCRIPTION_LIMITS.free } /** * Format subscription status for display */ export function formatSubscriptionStatus(status: string): string { const statusMap: Record = { 'active': 'Active', 'cancelled': 'Cancelled', 'past_due': 'Past Due', 'trialing': 'Trial', 'incomplete': 'Incomplete', 'incomplete_expired': 'Expired', 'unpaid': 'Unpaid', 'expired': 'Expired' } return statusMap[status.toLowerCase()] || status } /** * Check if subscription status is considered "active" for access purposes */ export function isSubscriptionActive(status: string): boolean { return ['active', 'trialing'].includes(status.toLowerCase()) }