import { Router } from 'express';
import Stripe from 'stripe';
import { prisma } from '../config/database.js';
import { authenticate } from '../middleware/auth.js';
import { env } from '../config/env.js';
import { AppError } from '../middleware/errorHandler.js';

const router = Router();

const stripe = env.STRIPE_SECRET_KEY ? new Stripe(env.STRIPE_SECRET_KEY) : null;

// --- Create payment intent for confirmed booking ---
router.post('/create-intent', authenticate, async (req, res, next) => {
  try {
    const { bookingId } = req.body;
    if (!stripe) throw new AppError(500, 'Stripe not configured');
    if (!bookingId) throw new AppError(400, 'Booking ID required');

    const booking = await prisma.booking.findUnique({ where: { id: bookingId } });
    if (!booking) throw new AppError(404, 'Booking not found');
    if (booking.tenantId !== req.userId) throw new AppError(403, 'Not authorized');
    if (booking.status !== 'CONFIRMED') throw new AppError(400, 'Booking must be confirmed before payment');

    // Check if already paid
    const existingPayment = await prisma.bookingPayment.findFirst({
      where: { bookingId, status: 'COMPLETED', type: 'RENTAL_BOOKING' },
    });
    if (existingPayment) throw new AppError(400, 'Booking already paid');

    const amountInCents = Math.round(booking.totalAmount * 100);

    const paymentIntent = await stripe.paymentIntents.create({
      amount: amountInCents,
      currency: 'usd',
      metadata: { bookingId, tenantId: req.userId!, landlordId: booking.landlordId },
    });

    await prisma.bookingPayment.create({
      data: {
        bookingId,
        stripePaymentId: paymentIntent.id,
        amount: booking.totalAmount,
        type: 'RENTAL_BOOKING',
        status: 'PENDING',
      },
    });

    await prisma.booking.update({
      where: { id: bookingId },
      data: { stripePaymentIntentId: paymentIntent.id },
    });

    res.json({ clientSecret: paymentIntent.client_secret });
  } catch (error) {
    next(error);
  }
});

// --- Stripe webhook ---
router.post('/webhook', async (req, res, next) => {
  try {
    if (!stripe) throw new AppError(500, 'Stripe not configured');

    const sig = req.headers['stripe-signature'] as string;
    const event = stripe.webhooks.constructEvent(req.body, sig, env.STRIPE_WEBHOOK_SECRET);

    if (event.type === 'payment_intent.succeeded') {
      const paymentIntent = event.data.object;
      const { bookingId } = paymentIntent.metadata;

      if (bookingId) {
        await prisma.bookingPayment.updateMany({
          where: { stripePaymentId: paymentIntent.id },
          data: { status: 'COMPLETED' },
        });

        // Move booking to ACTIVE if start date has passed, otherwise keep CONFIRMED
        const booking = await prisma.booking.findUnique({ where: { id: bookingId } });
        if (booking && booking.status === 'CONFIRMED') {
          const newStatus = booking.startDate <= new Date() ? 'ACTIVE' : 'CONFIRMED';
          await prisma.booking.update({ where: { id: bookingId }, data: { status: newStatus } });
        }
      }
    } else if (event.type === 'payment_intent.payment_failed') {
      const paymentIntent = event.data.object;

      await prisma.bookingPayment.updateMany({
        where: { stripePaymentId: paymentIntent.id },
        data: { status: 'FAILED' },
      });
    }

    res.json({ received: true });
  } catch (error) {
    next(error);
  }
});

// --- Payment history ---
router.get('/history', authenticate, async (req, res, next) => {
  try {
    const payments = await prisma.bookingPayment.findMany({
      where: {
        booking: {
          OR: [
            { tenantId: req.userId },
            { landlordId: req.userId },
          ],
        },
      },
      include: {
        booking: {
          select: {
            id: true,
            rentalListing: { select: { id: true, title: true, images: { take: 1, orderBy: { order: 'asc' } } } },
          },
        },
      },
      orderBy: { createdAt: 'desc' },
    });
    res.json(payments);
  } catch (error) {
    next(error);
  }
});

export default router;
