const express = require('express');
const router = express.Router();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const db = require('../../database/db');
const notificationService = require('../../services/notificationService');

/**
 * Stripe webhook endpoint
 * Handles subscription lifecycle events
 * 
 * Note: This endpoint uses express.raw() middleware for signature verification
 * Set this up in server.js before the main JSON body parser
 */
router.post('/', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    // Verify webhook signature
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    console.error('⚠️  Webhook signature verification failed:', err.message);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  console.log(`✅ Webhook received: ${event.type}`);

  // Handle event
  try {
    switch (event.type) {
      case 'customer.subscription.created':
        await handleSubscriptionCreated(event.data.object);
        break;

      case 'customer.subscription.updated':
        await handleSubscriptionUpdated(event.data.object);
        break;

      case 'customer.subscription.deleted':
        await handleSubscriptionDeleted(event.data.object);
        break;

      case 'invoice.payment_succeeded':
        await handlePaymentSucceeded(event.data.object);
        break;

      case 'invoice.payment_failed':
        await handlePaymentFailed(event.data.object);
        break;

      case 'customer.subscription.trial_will_end':
        await handleTrialWillEnd(event.data.object);
        break;

      default:
        console.log(`Unhandled event type: ${event.type}`);
    }

    res.json({ received: true });

  } catch (error) {
    console.error('Error processing webhook:', error);
    res.status(500).json({ error: 'Webhook processing failed' });
  }
});

/**
 * Handle subscription created
 */
async function handleSubscriptionCreated(subscription) {
  console.log(`[Webhook] Subscription created: ${subscription.id}`);

  // Subscription is already created in premiumService.subscribe()
  // This webhook just confirms it
}

/**
 * Handle subscription updated
 */
async function handleSubscriptionUpdated(subscription) {
  console.log(`[Webhook] Subscription updated: ${subscription.id}`);

  await db.query(
    `UPDATE premium_subscriptions 
     SET current_period_end = to_timestamp($2),
         cancel_at_period_end = $3,
         status = $4,
         updated_at = NOW()
     WHERE stripe_subscription_id = $1`,
    [
      subscription.id,
      subscription.current_period_end,
      subscription.cancel_at_period_end,
      subscription.status
    ]
  );

  // Update domain expiration if applicable
  await db.query(
    `UPDATE blockchain_domains 
     SET expires_at = to_timestamp($2)
     WHERE owner_user_id IN (
       SELECT user_id FROM premium_subscriptions 
       WHERE stripe_subscription_id = $1
     )`,
    [subscription.id, subscription.current_period_end]
  );
}

/**
 * Handle subscription deleted/cancelled
 */
async function handleSubscriptionDeleted(subscription) {
  console.log(`[Webhook] Subscription deleted: ${subscription.id}`);

  // Update subscription status
  await db.query(
    `UPDATE premium_subscriptions 
     SET status = 'cancelled', 
         cancelled_at = NOW(),
         updated_at = NOW()
     WHERE stripe_subscription_id = $1`,
    [subscription.id]
  );

  // Downgrade user to free tier
  const subResult = await db.query(
    `SELECT user_id FROM premium_subscriptions 
     WHERE stripe_subscription_id = $1`,
    [subscription.id]
  );

  if (subResult.rows.length > 0) {
    const userId = subResult.rows[0].user_id;

    await db.query(
      `UPDATE users SET premium_tier = 'free' WHERE id = $1`,
      [userId]
    );

    console.log(`[Webhook] User ${userId} downgraded to free tier`);

    // Send notification to user about downgrade
    await notificationService.notifySubscriptionDowngrade(userId);
  }
}

/**
 * Handle successful payment
 */
async function handlePaymentSucceeded(invoice) {
  console.log(`[Webhook] Payment succeeded for invoice: ${invoice.id}`);

  // Log the transaction
  if (invoice.customer && invoice.subscription) {
    const subResult = await db.query(
      `SELECT user_id FROM premium_subscriptions 
       WHERE stripe_subscription_id = $1`,
      [invoice.subscription]
    );

    if (subResult.rows.length > 0) {
      await db.query(
        `INSERT INTO payment_transactions 
         (user_id, transaction_type, amount_usd, stripe_payment_intent_id, stripe_invoice_id, status)
         VALUES ($1, 'subscription_renewal', $2, $3, $4, 'succeeded')`,
        [
          subResult.rows[0].user_id,
          invoice.amount_paid / 100, // Convert from cents
          invoice.payment_intent,
          invoice.id
        ]
      );

      console.log(`[Webhook] Payment logged for user ${subResult.rows[0].user_id}`);

      // Send receipt email to user
      const amount = invoice.amount_paid / 100;
      await notificationService.notifyPaymentSuccess(
        subResult.rows[0].user_id,
        amount,
        invoice.id
      );
    }
  }
}

/**
 * Handle failed payment
 */
async function handlePaymentFailed(invoice) {
  console.log(`[Webhook] Payment failed for invoice: ${invoice.id}`);

  // Log failed transaction
  if (invoice.customer && invoice.subscription) {
    const subResult = await db.query(
      `SELECT user_id FROM premium_subscriptions 
       WHERE stripe_subscription_id = $1`,
      [invoice.subscription]
    );

    if (subResult.rows.length > 0) {
      const userId = subResult.rows[0].user_id;

      await db.query(
        `INSERT INTO payment_transactions 
         (user_id, transaction_type, amount_usd, stripe_payment_intent_id, stripe_invoice_id, status)
         VALUES ($1, 'subscription_renewal', $2, $3, $4, 'failed')`,
        [
          userId,
          invoice.amount_due / 100,
          invoice.payment_intent,
          invoice.id
        ]
      );

      console.log(`[Webhook] Failed payment logged for user ${userId}`);

      // Send notification to user about failed payment
      const amount = invoice.amount_due / 100;
      const reason = invoice.last_payment_error?.message || 'Unknown error';
      await notificationService.notifyPaymentFailed(userId, amount, reason);
    }
  }
}

/**
 * Handle trial ending soon
 */
async function handleTrialWillEnd(subscription) {
  console.log(`[Webhook] Trial ending soon for subscription: ${subscription.id}`);

  const subResult = await db.query(
    `SELECT user_id FROM premium_subscriptions 
     WHERE stripe_subscription_id = $1`,
    [subscription.id]
  );

  if (subResult.rows.length > 0) {
    const userId = subResult.rows[0].user_id;

    // Calculate days remaining in trial
    const trialEnd = new Date(subscription.trial_end * 1000);
    const now = new Date();
    const daysRemaining = Math.ceil((trialEnd - now) / (1000 * 60 * 60 * 24));

    // Send notification to user that trial is ending
    await notificationService.notifyTrialEnding(userId, daysRemaining);
    console.log(`[Webhook] Trial ending notification sent to user ${userId}`);
  }
}

module.exports = router;
