import Stripe from 'stripe'
import { SubscriptionPlan, SubscriptionTier } from '@prisma/client'

if (!process.env.STRIPE_SECRET_KEY) {
  console.warn('STRIPE_SECRET_KEY not configured - Stripe integration disabled')
}

const stripe = process.env.STRIPE_SECRET_KEY
  ? new Stripe(process.env.STRIPE_SECRET_KEY)
  : null

export interface PlanMapping {
  plan: SubscriptionPlan
  tier: SubscriptionTier
  tokenLimit: number
  tools: string[]
}

const STARTER_TOOLS = [
  'nextcloud', 'keycloak', 'chatwoot', 'poste', 'n8n',
  'calcom', 'umami', 'uptime-kuma', 'vaultwarden', 'portainer',
]

const PRO_TOOLS = [
  ...STARTER_TOOLS,
  'ghost', 'nocodb', 'listmonk', 'gitea', 'minio',
  'penpot', 'typebot', 'windmill', 'redash', 'glitchtip',
]

/**
 * Map a Stripe Price ID to a LetsBe plan
 */
function mapPriceToplan(priceId: string): PlanMapping | null {
  const starterPriceId = process.env.STRIPE_STARTER_PRICE_ID
  const proPriceId = process.env.STRIPE_PRO_PRICE_ID

  if (priceId === starterPriceId) {
    return {
      plan: SubscriptionPlan.STARTER,
      tier: SubscriptionTier.ADVANCED,
      tokenLimit: 10000,
      tools: STARTER_TOOLS,
    }
  }

  if (priceId === proPriceId) {
    return {
      plan: SubscriptionPlan.PRO,
      tier: SubscriptionTier.HUB_DASHBOARD,
      tokenLimit: 50000,
      tools: PRO_TOOLS,
    }
  }

  return null
}

class StripeService {
  private static instance: StripeService

  static getInstance(): StripeService {
    if (!StripeService.instance) {
      StripeService.instance = new StripeService()
    }
    return StripeService.instance
  }

  /**
   * Check if Stripe is configured and available
   */
  isConfigured(): boolean {
    return stripe !== null
  }

  /**
   * Verify a webhook signature and construct the event
   */
  constructWebhookEvent(rawBody: string | Buffer, signature: string): Stripe.Event {
    if (!stripe) {
      throw new Error('Stripe is not configured')
    }

    const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET
    if (!webhookSecret) {
      throw new Error('STRIPE_WEBHOOK_SECRET is not configured')
    }

    return stripe.webhooks.constructEvent(rawBody, signature, webhookSecret)
  }

  /**
   * Create a Stripe Checkout Session for a given price
   */
  async createCheckoutSession(params: {
    priceId: string
    customerEmail?: string
    successUrl: string
    cancelUrl: string
    metadata?: Record<string, string>
  }): Promise<Stripe.Checkout.Session> {
    if (!stripe) {
      throw new Error('Stripe is not configured')
    }

    return stripe.checkout.sessions.create({
      mode: 'subscription',
      payment_method_types: ['card'],
      line_items: [
        {
          price: params.priceId,
          quantity: 1,
        },
      ],
      customer_email: params.customerEmail,
      success_url: params.successUrl,
      cancel_url: params.cancelUrl,
      metadata: params.metadata,
    })
  }

  /**
   * Map a Stripe price ID to a LetsBe plan configuration
   */
  mapPriceToPlan(priceId: string): PlanMapping | null {
    return mapPriceToplan(priceId)
  }

  /**
   * Extract plan info from a checkout session
   */
  extractPlanFromSession(session: Stripe.Checkout.Session): PlanMapping | null {
    // Get the price ID from the line items (available via expand or metadata)
    const priceId = session.metadata?.price_id
    if (priceId) {
      return this.mapPriceToPlan(priceId)
    }

    // Fallback: check metadata for plan name
    const planName = session.metadata?.plan
    if (planName === 'starter') {
      return {
        plan: SubscriptionPlan.STARTER,
        tier: SubscriptionTier.ADVANCED,
        tokenLimit: 10000,
        tools: STARTER_TOOLS,
      }
    }
    if (planName === 'professional' || planName === 'pro') {
      return {
        plan: SubscriptionPlan.PRO,
        tier: SubscriptionTier.HUB_DASHBOARD,
        tokenLimit: 50000,
        tools: PRO_TOOLS,
      }
    }

    return null
  }
}

export const stripeService = StripeService.getInstance()
