import { Router } from 'express';
import { authenticate } from '../../middleware/auth';
import { requireRoles } from '../../middleware/rbac';
import { Role, ErrorCode } from '@saferoute/constants';
import { prisma } from '../../config/database';
import { sendSuccess, sendError, sendPaginated } from '../../utils/response';

export const subscriptionRoutes = Router();

subscriptionRoutes.get('/', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const page = parseInt(req.query.page as string) || 1; const limit = parseInt(req.query.limit as string) || 20;
    const [subs, total] = await Promise.all([
      prisma.subscription.findMany({ skip: (page - 1) * limit, take: limit, include: { school: { select: { id: true, name: true } } }, orderBy: { createdAt: 'desc' } }),
      prisma.subscription.count(),
    ]);
    sendPaginated(res, subs, total, page, limit);
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to list subscriptions.'); }
});

subscriptionRoutes.post('/', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const { schoolId, planName, studentLimit, vehicleLimit, startDate, endDate } = req.body;
    const sub = await prisma.subscription.create({ data: { schoolId, planName, studentLimit, vehicleLimit, startDate: new Date(startDate), endDate: new Date(endDate) } });
    sendSuccess(res, { id: sub.id }, 'Subscription created', 201);
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to create subscription.'); }
});

subscriptionRoutes.patch('/:subscriptionId', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const { planName, studentLimit, vehicleLimit, endDate, status } = req.body;
    const sub = await prisma.subscription.update({
      where: { id: req.params.subscriptionId },
      data: { ...(planName && { planName }), ...(studentLimit && { studentLimit }), ...(vehicleLimit && { vehicleLimit }), ...(endDate && { endDate: new Date(endDate) }), ...(status && { status }) },
    });
    sendSuccess(res, { id: sub.id, status: sub.status }, 'Subscription updated');
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to update subscription.'); }
});

subscriptionRoutes.get('/invoices', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const page = parseInt(req.query.page as string) || 1; const limit = parseInt(req.query.limit as string) || 20;
    const [invoices, total] = await Promise.all([
      prisma.invoice.findMany({ skip: (page - 1) * limit, take: limit, include: { school: { select: { name: true } } }, orderBy: { createdAt: 'desc' } }),
      prisma.invoice.count(),
    ]);
    sendPaginated(res, invoices, total, page, limit);
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to list invoices.'); }
});

subscriptionRoutes.post('/invoices', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const { schoolId, subscriptionId, amount, currency, dueDate } = req.body;
    const invoice = await prisma.invoice.create({ data: { schoolId, subscriptionId, amount, currency, dueDate: new Date(dueDate) } });
    sendSuccess(res, { id: invoice.id }, 'Invoice created', 201);
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to create invoice.'); }
});

subscriptionRoutes.get('/payments', authenticate, requireRoles(Role.OWNER, Role.FINANCE_MANAGER), async (req, res) => {
  try {
    const payments = await prisma.payment.findMany({ include: { invoice: { include: { school: { select: { name: true } } } } }, orderBy: { paidAt: 'desc' }, take: 100 });
    sendSuccess(res, payments);
  } catch (error) { sendError(res, ErrorCode.SERVER_ERROR, 'Failed to list payments.'); }
});
