import { stripe } from "./stripe-client"
import { prisma } from "./prisma-client"
import { SUBSCRIPTION_PLANS } from "./subscription-config"
import { checkAndResetSubscriptionPeriod } from "./subscription-utils"

/**
 * Create a checkout session for a subscription
 */
export async function createCheckoutSession(
  userId: string,
  priceId: string,
  options?: {
    successUrl?: string
    cancelUrl?: string
    period?: "monthly" | "yearly"
  },
): Promise<string> {
  try {
    // Get user info
    const user = await prisma.users.findUnique({
      where: { user_id: userId },
      include: { subscriptions: true },
    })

    if (!user) {
      throw new Error(`User not found: ${userId}`)
    }

    // Use existing Stripe customer or create new one
    let customerId = user.subscriptions?.stripe_customer_id

    if (!customerId && user.email) {
      const customer = await stripe.customers.create({
        email: user.email,
        name: user.name || undefined,
        metadata: {
          userId,
          github_username: user.github_username || "",
        },
      })
      customerId = customer.id
    }

    // Determine period from priceId if not specified
    const period =
      options?.period || (priceId === process.env.STRIPE_PRO_PRICE_YEARLY_ID ? "yearly" : "monthly")

    // Ensure URLs have proper scheme for Stripe
    const baseUrl = process.env.WEBAPP_URL || "http://localhost:3000"
    const webappUrl = baseUrl.startsWith("http") ? baseUrl : `https://${baseUrl}`

    // Create checkout session
    const session = await stripe.checkout.sessions.create({
      customer: customerId,
      line_items: [{ price: priceId, quantity: 1 }],
      mode: "subscription",
      success_url: options?.successUrl || `${webappUrl}/app/billing?success=true`,
      cancel_url: options?.cancelUrl || `${webappUrl}/app/billing?canceled=true`,
      allow_promotion_codes: true,
      metadata: {
        userId,
        period,
      },
      subscription_data: {
        metadata: {
          userId,
          period,
        },
      },
    })

    return session.url || ""
  } catch (error) {
    console.error("Error creating checkout session:", error)
    throw error
  }
}

// common/src/subscription-functions.ts
export async function cancelSubscription(userId: string): Promise<void> {
  try {
    // Find the subscription
    const subscription = await prisma.subscriptions.findUnique({
      where: { user_id: userId },
    })

    if (!subscription?.stripe_subscription_id) {
      throw new Error("No active subscription found")
    }

    // Cancel at period end
    await stripe.subscriptions.update(subscription.stripe_subscription_id, {
      cancel_at_period_end: true,
    })

    // Update subscription status in database
    await prisma.subscriptions.update({
      where: { user_id: userId },
      data: {
        cancel_at_period_end: true,
        cancellation_request_date: new Date(),
      },
    })
  } catch (error) {
    console.error("Error canceling subscription:", error)
    throw error
  }
}

/**
 * Check if a user has exceeded their subscription limits
 */
export async function checkSubscriptionLimits(userId: string): Promise<{
  canOptimize: boolean
  remainingCount: number
  tier: string
}> {
  try {
    let subscription = await checkAndResetSubscriptionPeriod(userId)

    // Create a free tier subscription if none exists
    if (!subscription) {
      subscription = await prisma.subscriptions.create({
        data: {
          user_id: userId,
          plan_type: "free",
          optimizations_limit: SUBSCRIPTION_PLANS.FREE.optimizations,
          subscription_status: "active",
          optimizations_used: 0,
        },
      })
    }

    const isActive = subscription.subscription_status === "active"
    const remaining = subscription.optimizations_limit - subscription.optimizations_used

    return {
      canOptimize: isActive && remaining > 0,
      remainingCount: Math.max(0, remaining),
      tier: subscription.plan_type,
    }
  } catch (error) {
    console.error("Error checking subscription limits:", error)
    // Default to allowing optimization in case of error
    return {
      canOptimize: true,
      remainingCount: 999,
      tier: "error",
    }
  }
}

/**
 * Reset usage counts for all subscriptions (can be scheduled monthly)
 */
export async function resetMonthlyUsageCounts(): Promise<number> {
  try {
    const result = await prisma.subscriptions.updateMany({
      where: {
        subscription_status: "active",
      },
      data: {
        optimizations_used: 0,
      },
    })

    return result.count
  } catch (error) {
    console.error("Error resetting usage counts:", error)
    throw error
  }
}

export async function getSubscription(userId: string) {
  try {
    // Directly fetch subscription from DB
    const subscription = await prisma.subscriptions.findUnique({
      where: { user_id: userId },
    })

    if (!subscription) {
      return {
        plan_type: "free",
        optimizations_used: 0,
        optimizations_limit: SUBSCRIPTION_PLANS.FREE.optimizations,
        subscription_status: "active",
        cancel_at_period_end: false,
        current_period_end: null,
        total_lifetime_optimizations: 0,
      }
    }

    return subscription
  } catch (error) {
    console.error("Error fetching subscription:", error)
    return null
  }
}

export async function reactivateSubscription(userId: string): Promise<void> {
  try {
    const subscription = await prisma.subscriptions.findUnique({
      where: { user_id: userId },
    })

    if (!subscription?.stripe_subscription_id) {
      throw new Error("No subscription found to reactivate")
    }

    // Update the subscription in Stripe to remove cancellation
    await stripe.subscriptions.update(subscription.stripe_subscription_id, {
      cancel_at_period_end: false,
    })

    // Update subscription in database
    await prisma.subscriptions.update({
      where: { user_id: userId },
      data: {
        cancel_at_period_end: false,
        cancellation_request_date: null,
      },
    })
  } catch (error) {
    console.error("Error reactivating subscription:", error)
    throw error
  }
}
