import express from 'express';
import crypto from 'crypto';
import { subscriptionDb, paymentDb, userDb, PLAN_DURATIONS } from '../database/db.js';

const router = express.Router();

// Plan prices in paise (INR × 100) — source of truth
const PLAN_PRICES = {
  monthly:       { amount: 49900,  original: 49900  },  // ₹499
  'half-yearly': { amount: 249900, original: 249900 },  // ₹2,499
  yearly:        { amount: 49900,  original: 499900 },  // ₹499 offer (original ₹4,999)
};

// Plan tier ordering — higher number = higher tier
const PLAN_TIERS = { monthly: 1, 'half-yearly': 2, yearly: 3 };

// Lazy-load Razorpay instance
let _razorpay = null;
async function getRazorpay() {
  if (_razorpay) return _razorpay;
  const keyId = process.env.RAZORPAY_KEY_ID?.trim();
  const keySecret = process.env.RAZORPAY_KEY_SECRET?.trim();
  if (!keyId || !keySecret) throw new Error('Razorpay credentials not configured');
  const Razorpay = (await import('razorpay')).default;
  _razorpay = new Razorpay({ key_id: keyId, key_secret: keySecret });
  return _razorpay;
}

// ─── Create Order ───────────────────────────────────────────────────────────────
// Body: { planId, isDowngrade? }
// isDowngrade: if true, uses changePlan (cancels current sub + starts fresh)
// otherwise uses createSub (extends from current expiry for upgrades/renewals)
router.post('/create-order', async (req, res) => {
  try {
    const userId = req.user.id;
    const { planId, isDowngrade } = req.body;

    const plan = PLAN_PRICES[planId];
    if (!planId || !plan) {
      return res.status(400).json({ error: 'Invalid plan' });
    }

    const amountPaise = plan.amount;
    const razorpay = await getRazorpay();

    const notes = { userId: String(userId), planId };
    if (plan.original !== plan.amount) {
      notes.originalPrice = String(plan.original);
      notes.offerPrice = String(plan.amount);
    }
    if (isDowngrade) notes.isDowngrade = 'true';

    const order = await razorpay.orders.create({
      amount: amountPaise,
      currency: 'INR',
      receipt: `upfyn_${userId}_${planId}_${Date.now()}`,
      notes,
    });

    // Record pending payment
    await paymentDb.createPayment(userId, planId, amountPaise, 'INR', order.id);

    res.json({
      orderId: order.id,
      amount: amountPaise,
      originalAmount: plan.original,
      currency: 'INR',
    });
  } catch (error) {
    res.status(500).json({ error: 'Could not create order' });
  }
});

// ─── Verify Payment ─────────────────────────────────────────────────────────────
// Body: { orderId, paymentId, signature, planId, isDowngrade? }
router.post('/verify', async (req, res) => {
  try {
    const userId = req.user.id;
    const { orderId, paymentId, signature, planId, isDowngrade } = req.body;

    if (!orderId || !paymentId || !signature || !planId) {
      return res.status(400).json({ error: 'Missing payment details' });
    }

    // Verify Razorpay signature
    const keySecret = process.env.RAZORPAY_KEY_SECRET?.trim();
    if (!keySecret) return res.status(500).json({ error: 'Server payment config missing' });

    const expectedSig = crypto
      .createHmac('sha256', keySecret)
      .update(`${orderId}|${paymentId}`)
      .digest('hex');

    if (expectedSig !== signature) {
      await paymentDb.markFailed(orderId);
      return res.status(400).json({ error: 'Invalid payment signature' });
    }

    // Look up the pending payment to get the amount
    const payment = await paymentDb.getByOrderId(orderId);
    if (!payment) {
      return res.status(404).json({ error: 'Order not found' });
    }

    if (payment.user_id !== userId) {
      return res.status(403).json({ error: 'Order does not belong to this user' });
    }

    let sub;
    if (isDowngrade) {
      // Downgrade: cancel current sub and create new one starting now
      sub = await subscriptionDb.changePlan(
        userId, planId, payment.amount, payment.currency,
        orderId, paymentId, signature
      );
    } else {
      // Upgrade or new: extends from current expiry (or starts now if no active sub)
      sub = await subscriptionDb.createSub(
        userId, planId, payment.amount, payment.currency,
        orderId, paymentId, signature
      );
    }

    // Mark payment as paid
    await paymentDb.markPaid(orderId, paymentId, signature, sub.id);

    // Grant paid access
    await userDb.setAccessOverride(userId, 'paid');

    res.json({
      success: true,
      subscription: {
        id: sub.id,
        planId: sub.planId,
        status: sub.status,
        startsAt: sub.startsAt,
        expiresAt: sub.expiresAt,
      },
    });
  } catch (error) {
    res.status(500).json({ error: 'Payment verification failed' });
  }
});

// ─── Get Current Subscription ───────────────────────────────────────────────────
router.get('/subscription', async (req, res) => {
  try {
    await subscriptionDb.expireOverdue();
    const sub = await subscriptionDb.getActiveSub(req.user.id);
    res.json({ subscription: sub || null });
  } catch (error) {
    res.status(500).json({ error: 'Could not fetch subscription' });
  }
});

// ─── Get Payment History ────────────────────────────────────────────────────────
router.get('/history', async (req, res) => {
  try {
    const payments = await paymentDb.getUserPayments(req.user.id);
    const subscriptions = await subscriptionDb.getAllSubs(req.user.id);
    res.json({ payments, subscriptions });
  } catch (error) {
    res.status(500).json({ error: 'Could not fetch payment history' });
  }
});

// ─── Cancel Subscription ────────────────────────────────────────────────────────
router.post('/cancel', async (req, res) => {
  try {
    const sub = await subscriptionDb.getActiveSub(req.user.id);
    if (!sub) {
      return res.status(404).json({ error: 'No active subscription found' });
    }
    const cancelled = await subscriptionDb.cancelSub(req.user.id, sub.id);
    res.json({ success: cancelled });
  } catch (error) {
    res.status(500).json({ error: 'Could not cancel subscription' });
  }
});

// ─── Invoice / Receipt Details ─────────────────────────────────────────────────
// Returns payment details for a given payment ID (for receipt / invoice view)
router.get('/invoice/:paymentId', async (req, res) => {
  try {
    const payments = await paymentDb.getUserPayments(req.user.id);
    const payment = payments.find(p => String(p.id) === req.params.paymentId);
    if (!payment) {
      return res.status(404).json({ error: 'Payment not found' });
    }

    // Fetch payment details from Razorpay if payment ID is available
    let razorpayDetails = null;
    if (payment.razorpay_payment_id) {
      try {
        const razorpay = await getRazorpay();
        razorpayDetails = await razorpay.payments.fetch(payment.razorpay_payment_id);
      } catch { /* Razorpay fetch failed — return local data only */ }
    }

    const planName = {
      monthly: 'Monthly Plan',
      'half-yearly': '6-Month Plan',
      yearly: 'Annual Plan',
    }[payment.plan_id] || payment.plan_id;

    res.json({
      id: payment.id,
      planId: payment.plan_id,
      planName,
      amount: payment.amount,
      currency: payment.currency || 'INR',
      status: payment.status,
      createdAt: payment.created_at,
      razorpayOrderId: payment.razorpay_order_id || null,
      razorpayPaymentId: payment.razorpay_payment_id || null,
      // Razorpay payment details (method, email, contact, etc.)
      method: razorpayDetails?.method || null,
      email: razorpayDetails?.email || null,
      contact: razorpayDetails?.contact || null,
      description: razorpayDetails?.description || null,
    });
  } catch (error) {
    res.status(500).json({ error: 'Could not fetch invoice details' });
  }
});

export default router;
