const express = require('express');
const router = express.Router();
const { db } = require('../db/database');
const { requireAuth } = require('../middleware/auth');
const config = require('../config');

const appUrl = process.env.APP_URL || '';

let stripe = null;
if (config.stripeSecretKey) {
  stripe = require('stripe')(config.stripeSecretKey);
}

// Create checkout session - user clicks "Upgrade" on a plan
router.post('/checkout', requireAuth, async (req, res) => {
  if (!stripe) return res.status(503).json({ error: 'Stripe not configured' });

  const { plan_id, interval } = req.body; // interval: 'monthly' or 'yearly'
  if (!plan_id) return res.status(400).json({ error: 'plan_id required' });

  const plan = db.prepare('SELECT * FROM plans WHERE id = ?').get(plan_id);
  if (!plan) return res.status(404).json({ error: 'Plan not found' });

  const priceId = interval === 'yearly' ? plan.stripe_price_yearly : plan.stripe_price_monthly;
  if (!priceId) return res.status(400).json({ error: `No Stripe price configured for ${plan_id} (${interval || 'monthly'})` });

  try {
    // Get or create Stripe customer
    let customerId = req.user.stripe_customer_id;
    if (!customerId) {
      const customer = await stripe.customers.create({
        email: req.user.email,
        metadata: { user_id: req.user.id, name: req.user.name || '' },
      });
      customerId = customer.id;
      db.prepare('UPDATE users SET stripe_customer_id = ? WHERE id = ?').run(customerId, req.user.id);
    }

    // If user already has an active subscription, create a portal session to manage it
    if (req.user.stripe_subscription_id) {
      const portal = await stripe.billingPortal.sessions.create({
        customer: customerId,
        return_url: `${req.headers.origin || appUrl}/#/settings`,
      });
      return res.json({ url: portal.url, type: 'portal' });
    }

    // Create checkout session for new subscription
    const session = await stripe.checkout.sessions.create({
      customer: customerId,
      mode: 'subscription',
      payment_method_types: ['card'],
      // Renders the "Add promotion code" field on Stripe's hosted checkout page. For
      // API-created sessions this is the ONLY way to enable it — there is no Stripe Dashboard
      // toggle for it outside Payment Links (which we don't use). Do not remove thinking it's
      // redundant with a dashboard setting.
      allow_promotion_codes: true,
      line_items: [{ price: priceId, quantity: 1 }],
      success_url: `${req.headers.origin || appUrl}/#/settings?payment=success`,
      cancel_url: `${req.headers.origin || appUrl}/#/settings?payment=cancelled`,
      metadata: { user_id: req.user.id, plan_id },
      subscription_data: {
        metadata: { user_id: req.user.id, plan_id },
      },
    });

    res.json({ url: session.url, type: 'checkout' });
  } catch (err) {
    console.error('Stripe checkout error:', err.message);
    res.status(500).json({ error: 'Failed to create checkout session' });
  }
});

// Customer portal - manage existing subscription (change plan, cancel, update payment)
router.post('/portal', requireAuth, async (req, res) => {
  if (!stripe) return res.status(503).json({ error: 'Stripe not configured' });

  const customerId = req.user.stripe_customer_id;
  if (!customerId) return res.status(400).json({ error: 'No billing account found' });

  try {
    const session = await stripe.billingPortal.sessions.create({
      customer: customerId,
      return_url: `${req.headers.origin || appUrl}/#/settings`,
    });
    res.json({ url: session.url });
  } catch (err) {
    console.error('Stripe portal error:', err.message);
    res.status(500).json({ error: 'Failed to create portal session' });
  }
});

// Stripe webhook - handles all subscription lifecycle events
router.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  if (!stripe) return res.status(404).json({ error: 'Stripe not configured' });

  let event;
  try {
    if (!config.stripeWebhookSecret) {
      console.error('Stripe webhook secret not configured — rejecting unsigned webhook');
      return res.status(400).json({ error: 'Webhook secret not configured' });
    }
    event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], config.stripeWebhookSecret);
  } catch (err) {
    console.error('Webhook signature verification failed:', err.message);
    return res.status(400).json({ error: 'Invalid signature' });
  }

  console.log(`Stripe webhook: ${event.type}`);

  try {
    switch (event.type) {
      case 'checkout.session.completed': {
        const session = event.data.object;
        const userId = session.metadata?.user_id;
        const planId = session.metadata?.plan_id;
        if (userId && session.subscription) {
          db.prepare(`UPDATE users SET stripe_subscription_id = ?, plan_id = ?, subscription_status = 'active', updated_at = strftime('%s','now') WHERE id = ?`)
            .run(session.subscription, planId || 'starter', userId);
          console.log(`User ${userId} subscribed to ${planId} (sub: ${session.subscription})`);
        }
        break;
      }

      case 'customer.subscription.updated': {
        const sub = event.data.object;
        const userId = sub.metadata?.user_id;
        if (!userId) break;

        // Find plan by stripe price ID
        const priceId = sub.items?.data?.[0]?.price?.id;
        let planId = sub.metadata?.plan_id;
        if (priceId && !planId) {
          const plan = db.prepare('SELECT id FROM plans WHERE stripe_price_monthly = ? OR stripe_price_yearly = ?').get(priceId, priceId);
          if (plan) planId = plan.id;
        }

        const status = sub.status === 'active' ? 'active' : sub.status === 'past_due' ? 'past_due' : sub.status;
        const ends = sub.current_period_end || null;

        db.prepare(`UPDATE users SET plan_id = COALESCE(?, plan_id), subscription_status = ?, subscription_ends = ?, updated_at = strftime('%s','now') WHERE id = ?`)
          .run(planId, status, ends, userId);
        console.log(`Subscription updated for ${userId}: ${planId} (${status})`);
        break;
      }

      case 'customer.subscription.deleted': {
        const sub = event.data.object;
        const userId = sub.metadata?.user_id;
        if (userId) {
          db.prepare(`UPDATE users SET plan_id = 'free', subscription_status = 'cancelled', stripe_subscription_id = NULL, updated_at = strftime('%s','now') WHERE id = ?`)
            .run(userId);
          console.log(`Subscription cancelled for ${userId}`);
        }
        break;
      }

      case 'invoice.payment_failed': {
        const invoice = event.data.object;
        const subId = invoice.subscription;
        if (subId) {
          const user = db.prepare('SELECT id FROM users WHERE stripe_subscription_id = ?').get(subId);
          if (user) {
            db.prepare("UPDATE users SET subscription_status = 'past_due', updated_at = strftime('%s','now') WHERE id = ?").run(user.id);
            console.log(`Payment failed for user ${user.id}`);
          }
        }
        break;
      }
    }
  } catch (err) {
    console.error('Webhook processing error:', err.message);
  }

  res.json({ received: true });
});

module.exports = router;
