import { eq } from "drizzle-orm"; import { db } from "@/lib/db"; import { subscriptions, users } from "@/lib/schema"; const TRIAL_DAYS = 14; export interface SubscriptionStatus { isActive: boolean; status: "trialing" | "active" | "expired" | "canceled" | "canceling"; daysRemainingInTrial: number | null; trialEndsAt: Date | null; subscriptionEndsAt: Date | null; } /** * Check if a user has an active subscription or valid trial */ export async function checkSubscriptionStatus(userId: string): Promise { // Get user creation date const [user] = await db .select({ createdAt: users.createdAt }) .from(users) .where(eq(users.id, userId)) .limit(1); if (!user) { return { isActive: false, status: "expired", daysRemainingInTrial: null, trialEndsAt: null, subscriptionEndsAt: null, }; } // Get subscription record const [subscription] = await db .select() .from(subscriptions) .where(eq(subscriptions.userId, userId)) .limit(1); const now = new Date(); const trialEndsAt = new Date(user.createdAt); trialEndsAt.setDate(trialEndsAt.getDate() + TRIAL_DAYS); // If user has active or canceling subscription, they can use the service if (subscription?.status === "active" || subscription?.status === "canceling") { // If subscription is marked as canceling, return canceling status if (subscription.status === "canceling") { return { isActive: true, status: "canceling", daysRemainingInTrial: null, trialEndsAt: null, subscriptionEndsAt: subscription.currentPeriodEnd || null, }; } return { isActive: true, status: "active", daysRemainingInTrial: null, trialEndsAt: null, subscriptionEndsAt: subscription.currentPeriodEnd || null, }; } // If still in trial period if (now < trialEndsAt) { const daysRemaining = Math.ceil( (trialEndsAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24) ); return { isActive: true, status: "trialing", daysRemainingInTrial: daysRemaining, trialEndsAt, subscriptionEndsAt: null, }; } // Trial expired and no paid subscription if (subscription?.status === "canceled") { return { isActive: false, status: "canceled", daysRemainingInTrial: null, trialEndsAt, subscriptionEndsAt: null, }; } return { isActive: false, status: "expired", daysRemainingInTrial: null, trialEndsAt, subscriptionEndsAt: null, }; }