import { Router, Request, Response, NextFunction } from 'express';
import { authenticate } from '../../middleware/auth.middleware';
import { requireRole } from '../../middleware/rbac.middleware';
import { requireNonTemp } from '../../middleware/rbac.middleware';
import { validate } from '../../middleware/validate';
import { ticketsService } from './tickets.service';
import { validateTokenSchema, confirmCheckinSchema, manualCheckinSchema } from './ticketed-events.schemas';
import { prisma } from '../../config/database';
import { AppError } from '../../middleware/error-handler';
import { EVENTS_ROLES } from '../../utils/roles';
import { UserRole } from '@prisma/client';

const router = Router();

/** Require EVENTS_ROLES or canCreateTicketedEvents permission for check-in */
async function requireCheckinPermission(req: Request, _res: Response, next: NextFunction) {
  if (!req.user) return next(new AppError(401, 'Authentication required', 'AUTH_REQUIRED'));

  const userRoles = req.user.roles || [req.user.role];
  if (userRoles.some(r => EVENTS_ROLES.includes(r as UserRole))) {
    return next();
  }

  // Check user permissions
  const user = await prisma.user.findUnique({
    where: { id: req.user.id },
    select: { permissions: true },
  });
  const perms = (user?.permissions as Record<string, unknown>) || {};
  if (perms.canCreateTicketedEvents) {
    return next();
  }

  return next(new AppError(403, 'Insufficient permissions for check-in operations', 'FORBIDDEN'));
}

// All check-in routes require authentication + non-temp + events permission
router.use(authenticate, requireNonTemp, requireCheckinPermission);

// POST /validate — validate QR token (preview without marking checked in)
router.post('/validate', validate(validateTokenSchema), async (req: Request, res: Response, next: NextFunction) => {
  try {
    const result = await ticketsService.validateToken(req.body.token);
    res.json(result);
  } catch (err) { next(err); }
});

// POST /confirm — confirm check-in via QR token
router.post('/confirm', validate(confirmCheckinSchema), async (req: Request, res: Response, next: NextFunction) => {
  try {
    const result = await ticketsService.confirmCheckin(
      req.body.token,
      req.user!.id,
      req.body.notes,
    );
    res.json(result);
  } catch (err) { next(err); }
});

// POST /manual — manual check-in by code or email
router.post('/manual', validate(manualCheckinSchema), async (req: Request, res: Response, next: NextFunction) => {
  try {
    const result = await ticketsService.manualCheckin({
      eventId: req.body.eventId,
      ticketCode: req.body.ticketCode,
      holderEmail: req.body.holderEmail,
      checkedInByUserId: req.user!.id,
      notes: req.body.notes,
    });
    res.json(result);
  } catch (err) { next(err); }
});

// GET /event/:eventId/stats — live check-in stats
router.get('/event/:eventId/stats', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const eventId = req.params.eventId as string;
    const [totalTickets, checkedIn, recentCheckIns] = await Promise.all([
      prisma.ticket.count({ where: { eventId, status: { in: ['VALID', 'CHECKED_IN'] } } }),
      prisma.ticket.count({ where: { eventId, status: 'CHECKED_IN' } }),
      prisma.checkIn.findMany({
        where: { eventId },
        orderBy: { checkedInAt: 'desc' },
        take: 5,
        include: {
          ticket: { select: { ticketCode: true, holderName: true } },
        },
      }),
    ]);
    res.json({ totalTickets, checkedIn, remaining: totalTickets - checkedIn, recentCheckIns });
  } catch (err) { next(err); }
});

export { router as checkinRouter };
