import { Router } from 'express';
import Stripe from 'stripe';
import { prisma } from '../../config/database.js';
import { requireAdmin } from '../../middleware/requireRole.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;

// --- List all payouts ---
router.get('/', requireAdmin, async (req, res, next) => {
  try {
    const { page = '1', pageSize = '20', status } = req.query;
    const skip = (parseInt(page as string) - 1) * parseInt(pageSize as string);
    const take = parseInt(pageSize as string);

    const where: Record<string, unknown> = {};
    if (status) where.status = status;

    const [data, total] = await Promise.all([
      prisma.payout.findMany({
        where,
        include: {
          booking: {
            select: {
              id: true,
              rentalListing: { select: { id: true, title: true } },
              tenant: { select: { id: true, fullName: true } },
            },
          },
          landlord: { select: { id: true, fullName: true, email: true, stripeAccountId: true } },
        },
        skip, take,
        orderBy: { createdAt: 'desc' },
      }),
      prisma.payout.count({ where }),
    ]);

    res.json({ data, total, page: parseInt(page as string), pageSize: take, totalPages: Math.ceil(total / take) });
  } catch (error) {
    next(error);
  }
});

// --- Retry failed payout ---
router.patch('/:id/retry', requireAdmin, async (req, res, next) => {
  try {
    const payout = await prisma.payout.findUnique({
      where: { id: req.params.id },
      include: { landlord: true },
    });
    if (!payout) throw new AppError(404, 'Payout not found');
    if (payout.status !== 'FAILED' && payout.status !== 'PENDING') {
      throw new AppError(400, 'Can only retry failed or pending payouts');
    }

    if (!payout.landlord.stripeAccountId) {
      throw new AppError(400, 'Landlord has no Stripe Connect account');
    }

    if (stripe) {
      try {
        const transfer = await stripe.transfers.create({
          amount: Math.round(payout.netAmount * 100),
          currency: 'usd',
          destination: payout.landlord.stripeAccountId,
          metadata: { payoutId: payout.id, bookingId: payout.bookingId },
        });

        await prisma.payout.update({
          where: { id: payout.id },
          data: { status: 'COMPLETED', stripeTransferId: transfer.id },
        });

        // Notify landlord
        await prisma.notification.create({
          data: {
            userId: payout.landlordId,
            type: 'PAYOUT_SENT',
            title: 'Payout Sent',
            body: `Your payout of $${payout.netAmount.toFixed(2)} has been sent.`,
            data: { payoutId: payout.id },
          },
        });
      } catch {
        await prisma.payout.update({ where: { id: payout.id }, data: { status: 'FAILED' } });

        await prisma.notification.create({
          data: {
            userId: payout.landlordId,
            type: 'PAYOUT_FAILED',
            title: 'Payout Failed',
            body: `Your payout of $${payout.netAmount.toFixed(2)} failed. Our team is investigating.`,
            data: { payoutId: payout.id },
          },
        });
      }
    }

    const updated = await prisma.payout.findUnique({ where: { id: payout.id } });
    res.json(updated);
  } catch (error) {
    next(error);
  }
});

export default router;
