import prisma from '../services/prisma.js';
import asyncHandler from '../utils/asyncHandler.js';
import ApiError from '../utils/ApiError.js';
import { getStripe, isStripeConfigured } from '../services/stripe.service.js';
import { env, isProd } from '../config/env.js';

// GET /api/payments/config -> tells the frontend whether real payments are available
export const getConfig = asyncHandler(async (_req, res) => {
  res.json({ success: true, stripeConfigured: isStripeConfigured(), devUnlock: !isProd && !isStripeConfigured() });
});

// POST /api/payments/dev-grant { courseId }
// Development-only shortcut to unlock an exam WITHOUT Stripe, for local testing.
// Disabled entirely in production and whenever real Stripe keys are configured.
export const devGrant = asyncHandler(async (req, res) => {
  if (isProd || isStripeConfigured()) {
    throw ApiError.forbidden('Test-mode unlock is only available in development without Stripe keys');
  }
  const { courseId } = req.body;
  if (!courseId) throw ApiError.badRequest('courseId is required');

  const course = await prisma.course.findUnique({ where: { id: courseId } });
  if (!course) throw ApiError.notFound('Course not found');

  const existing = await prisma.purchase.findFirst({
    where: { userId: req.user.id, courseId, status: 'PAID' },
  });
  if (existing) return res.json({ success: true, message: 'Already unlocked', alreadyOwned: true });

  await prisma.purchase.create({
    data: {
      userId: req.user.id,
      courseId,
      amountCents: course.priceCents,
      currency: course.currency,
      status: 'PAID',
    },
  });
  res.json({ success: true, message: 'Full access granted (test mode)' });
});

// POST /api/payments/checkout  { courseId }
export const createCheckoutSession = asyncHandler(async (req, res) => {
  const { courseId } = req.body;
  if (!courseId) throw ApiError.badRequest('courseId is required');

  const course = await prisma.course.findUnique({
    where: { id: courseId },
    include: { vendor: { select: { name: true } } },
  });
  if (!course) throw ApiError.notFound('Course not found');
  if (course.isFree || course.priceCents === 0) {
    throw ApiError.badRequest('This exam is free, no purchase needed');
  }

  const already = await prisma.purchase.findFirst({
    where: { userId: req.user.id, courseId, status: 'PAID' },
  });
  if (already) throw ApiError.conflict('You already own this exam');

  const stripe = getStripe();
  if (!stripe) {
    throw ApiError.badRequest('Payments are not configured. Set STRIPE_SECRET_KEY in backend .env');
  }

  // Pending purchase record
  const purchase = await prisma.purchase.create({
    data: {
      userId: req.user.id,
      courseId,
      amountCents: course.priceCents,
      currency: course.currency,
      status: 'PENDING',
    },
  });

  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    payment_method_types: ['card'],
    customer_email: req.user.email,
    line_items: [
      {
        price_data: {
          currency: course.currency,
          unit_amount: course.priceCents,
          product_data: {
            name: `${course.vendor.name} — ${course.title}`,
            description: 'Full exam access on CertsNexus',
          },
        },
        quantity: 1,
      },
    ],
    metadata: { purchaseId: purchase.id, courseId, userId: req.user.id },
    success_url: `${env.clientUrl}/courses/${course.slug}?payment=success&session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${env.clientUrl}/courses/${course.slug}?payment=cancelled`,
  });

  await prisma.purchase.update({
    where: { id: purchase.id },
    data: { stripeSessionId: session.id },
  });

  res.json({ success: true, url: session.url, sessionId: session.id });
});

// Stripe webhook (raw body). Marks purchase PAID.
export const handleWebhook = asyncHandler(async (req, res) => {
  const stripe = getStripe();
  if (!stripe) return res.status(400).send('Stripe not configured');

  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(req.body, sig, env.stripeWebhookSecret);
  } catch (err) {
    return res.status(400).send(`Webhook signature verification failed: ${err.message}`);
  }

  if (event.type === 'checkout.session.completed') {
    const session = event.data.object;
    const purchaseId = session.metadata?.purchaseId;
    if (purchaseId) {
      await prisma.purchase.update({
        where: { id: purchaseId },
        data: {
          status: 'PAID',
          stripePaymentIntent: session.payment_intent?.toString() || null,
        },
      });
    }
  }

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

// Fallback for local/dev without webhooks: confirm via session id after redirect.
// POST /api/payments/confirm { sessionId }
export const confirmCheckout = asyncHandler(async (req, res) => {
  const { sessionId } = req.body;
  if (!sessionId) throw ApiError.badRequest('sessionId is required');

  const stripe = getStripe();
  if (!stripe) throw ApiError.badRequest('Payments are not configured');

  const session = await stripe.checkout.sessions.retrieve(sessionId);
  if (session.payment_status !== 'paid') {
    return res.json({ success: false, status: session.payment_status });
  }

  const purchase = await prisma.purchase.findUnique({ where: { stripeSessionId: sessionId } });
  if (purchase && purchase.userId === req.user.id && purchase.status !== 'PAID') {
    await prisma.purchase.update({
      where: { id: purchase.id },
      data: { status: 'PAID', stripePaymentIntent: session.payment_intent?.toString() || null },
    });
  }
  res.json({ success: true, status: 'paid' });
});

// GET /api/payments/admin/finance  (super admin) -> all purchases + revenue summary
export const adminFinance = asyncHandler(async (_req, res) => {
  const purchases = await prisma.purchase.findMany({
    orderBy: { createdAt: 'desc' },
    include: {
      user: { select: { id: true, name: true, email: true } },
      course: { select: { id: true, title: true, slug: true } },
    },
  });

  const paid = purchases.filter((p) => p.status === 'PAID');
  const totalRevenueCents = paid.reduce((sum, p) => sum + p.amountCents, 0);
  const currency = paid[0]?.currency || 'usd';

  res.json({
    success: true,
    purchases,
    summary: {
      totalRevenueCents,
      currency,
      paidCount: paid.length,
      pendingCount: purchases.filter((p) => p.status === 'PENDING').length,
      totalCount: purchases.length,
    },
    stripeConfigured: isStripeConfigured(),
  });
});

// GET /api/payments/my  -> courses the user owns
export const myPurchases = asyncHandler(async (req, res) => {
  const purchases = await prisma.purchase.findMany({
    where: { userId: req.user.id, status: 'PAID' },
    include: { course: { select: { id: true, title: true, slug: true } } },
    orderBy: { createdAt: 'desc' },
  });
  res.json({ success: true, purchases, stripeConfigured: isStripeConfigured() });
});
