import { Router, Request, Response, NextFunction } from 'express'; import { UserRole } from '@prisma/client'; import { galleryAdsService } from './gallery-ads.service'; import { createAdSchema, updateAdSchema, listAdsSchema, reorderAdsSchema, adAnalyticsQuerySchema } from './gallery-ads.schemas'; import { validate } from '../../middleware/validate'; import { authenticate } from '../../middleware/auth.middleware'; import { requireRole } from '../../middleware/rbac.middleware'; const router = Router(); router.use(authenticate); router.use(requireRole(UserRole.SUPER_ADMIN)); // GET /api/gallery-ads/admin — list all ads (paginated) router.get( '/', validate(listAdsSchema, 'query'), async (req: Request, res: Response, next: NextFunction) => { try { const result = await galleryAdsService.listAll(req.query as any); res.json(result); } catch (err) { next(err); } } ); // GET /api/gallery-ads/admin/analytics/aggregate — aggregate analytics across all ads router.get( '/analytics/aggregate', validate(adAnalyticsQuerySchema, 'query'), async (req: Request, res: Response, next: NextFunction) => { try { const { days } = req.query as any; const analytics = await galleryAdsService.getAggregateAnalytics(days); res.json(analytics); } catch (err) { next(err); } } ); // GET /api/gallery-ads/admin/:id/analytics — per-ad time-series analytics router.get( '/:id/analytics', validate(adAnalyticsQuerySchema, 'query'), async (req: Request, res: Response, next: NextFunction) => { try { const id = parseInt(req.params.id as string, 10); const { days } = req.query as any; const analytics = await galleryAdsService.getAdAnalytics(id, days); res.json(analytics); } catch (err) { next(err); } } ); // GET /api/gallery-ads/admin/:id — get single ad router.get('/:id', async (req: Request, res: Response, next: NextFunction) => { try { const id = parseInt(req.params.id as string, 10); const ad = await galleryAdsService.getById(id); if (!ad) { res.status(404).json({ error: 'Ad not found' }); return; } res.json(ad); } catch (err) { next(err); } }); // POST /api/gallery-ads/admin — create ad router.post( '/', validate(createAdSchema), async (req: Request, res: Response, next: NextFunction) => { try { const ad = await galleryAdsService.create(req.body); res.status(201).json(ad); } catch (err) { next(err); } } ); // PUT /api/gallery-ads/admin/reorder — bulk reorder router.put( '/reorder', validate(reorderAdsSchema), async (req: Request, res: Response, next: NextFunction) => { try { await galleryAdsService.reorder(req.body.ids); res.json({ success: true }); } catch (err) { next(err); } } ); // PUT /api/gallery-ads/admin/:id — update ad router.put( '/:id', validate(updateAdSchema), async (req: Request, res: Response, next: NextFunction) => { try { const id = parseInt(req.params.id as string, 10); const ad = await galleryAdsService.update(id, req.body); if (!ad) { res.status(404).json({ error: 'Ad not found' }); return; } res.json(ad); } catch (err) { if (err instanceof Error && err.message.includes('Cannot change type')) { res.status(400).json({ error: err.message }); return; } next(err); } } ); // DELETE /api/gallery-ads/admin/:id — delete ad router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => { try { const id = parseInt(req.params.id as string, 10); await galleryAdsService.delete(id); res.json({ success: true }); } catch (err) { if (err instanceof Error && err.message.includes('Cannot delete')) { res.status(400).json({ error: err.message }); return; } next(err); } }); export { router as galleryAdsAdminRouter };