import Stripe from 'stripe';
import { updateUserPlan, findUserById, findUserByStripeSubscriptionId, downgradeUser, updateSubscriptionStatus, updateSubscriptionPeriod } from '../models/user';

const STRIPE_KEY = process.env.STRIPE_SECRET_KEY || '';
if (!STRIPE_KEY || STRIPE_KEY === 'sk_test_placeholder') {
  console.warn('⚠️ STRIPE_SECRET_KEY not set or placeholder — billing features will be unavailable');
}
const stripe = new Stripe(STRIPE_KEY);

const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET || '';
if (!STRIPE_WEBHOOK_SECRET || STRIPE_WEBHOOK_SECRET === 'whsec_placeholder') {
  console.error('⚠️ WARNING: STRIPE_WEBHOOK_SECRET is not configured — webhook verification will reject all events');
}

const PRICE_IDS = {
  weekly: process.env.STRIPE_PRICE_WEEKLY || '',
  monthly: process.env.STRIPE_PRICE_MONTHLY || '',
};

export async function createCheckoutSession(
  userId: string,
  email: string,
  plan: 'weekly' | 'monthly',
  successUrl: string,
  cancelUrl: string
): Promise<string> {
  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    customer_email: email,
    line_items: [
      {
        price: PRICE_IDS[plan],
        quantity: 1,
      },
    ],
    success_url: successUrl,
    cancel_url: cancelUrl,
    metadata: {
      userId,
      plan,
    },
  });
  
  return session.url || '';
}

export async function createPortalSession(customerId: string, returnUrl: string): Promise<string> {
  const session = await stripe.billingPortal.sessions.create({
    customer: customerId,
    return_url: returnUrl,
  });
  
  return session.url;
}

export async function handleWebhook(payload: Buffer, signature: string): Promise<void> {
  const webhookSecret = STRIPE_WEBHOOK_SECRET;
  
  let event: Stripe.Event;
  
  try {
    event = stripe.webhooks.constructEvent(payload, signature, webhookSecret);
  } catch (err) {
    throw new Error('Webhook signature verification failed');
  }
  
  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      const userId = session.metadata?.userId;
      const plan = session.metadata?.plan as 'weekly' | 'monthly';
      
      if (userId && plan) {
        const subscription = await stripe.subscriptions.retrieve(session.subscription as string);
        const endsAt = new Date(subscription.current_period_end * 1000);
        
        await updateUserPlan(
          userId,
          plan,
          session.customer as string,
          session.subscription as string,
          endsAt
        );
        
        console.log(`User ${userId} upgraded to ${plan}`);
      }
      break;
    }
    
    case 'customer.subscription.updated': {
      const subscription = event.data.object as Stripe.Subscription;
      const user = await findUserByStripeSubscriptionId(subscription.id);
      if (user) {
        if (subscription.status === 'active') {
          await updateSubscriptionPeriod(user.id, new Date(subscription.current_period_end * 1000));
          console.log(`User ${user.id} subscription renewed`);
        } else if (subscription.status === 'past_due') {
          await updateSubscriptionStatus(user.id, 'past_due');
          console.log(`User ${user.id} subscription past_due`);
        } else if (subscription.status === 'canceled' || subscription.status === 'unpaid') {
          await downgradeUser(user.id);
          console.log(`User ${user.id} downgraded to free (status: ${subscription.status})`);
        }
      }
      break;
    }

    case 'customer.subscription.deleted': {
      const subscription = event.data.object as Stripe.Subscription;
      const user = await findUserByStripeSubscriptionId(subscription.id);
      if (user) {
        await downgradeUser(user.id);
        console.log(`User ${user.id} subscription deleted, downgraded to free`);
      }
      break;
    }

    case 'invoice.payment_failed': {
      const invoice = event.data.object as Stripe.Invoice;
      const subscriptionId = invoice.subscription as string;
      if (subscriptionId) {
        const user = await findUserByStripeSubscriptionId(subscriptionId);
        if (user) {
          await updateSubscriptionStatus(user.id, 'past_due');
          console.log(`User ${user.id} payment failed, marked past_due`);
        }
      }
      break;
    }
  }
}

export async function cancelSubscription(subscriptionId: string): Promise<void> {
  await stripe.subscriptions.cancel(subscriptionId);
}
