const express = require("express"); const router = express.Router(); const auth = require("../middleware/auth"); const { getCacheMiddleware, invalidateCacheByPattern } = require("../middleware/cache"); const gamificationService = require("../services/gamificationService"); const User = require("../models/User"); const logger = require("../utils/logger"); /** * @route GET /api/leaderboard/global * @desc Get global leaderboard (all time) * @access Public * @query limit (default 100), offset (default 0) */ router.get("/global", getCacheMiddleware(300), async (req, res) => { try { const limit = Math.min(parseInt(req.query.limit) || 100, 500); const offset = parseInt(req.query.offset) || 0; logger.info("Fetching global leaderboard", { limit, offset }); const leaderboard = await gamificationService.getGlobalLeaderboard(limit, offset); res.json({ success: true, count: leaderboard.length, limit, offset, data: leaderboard }); } catch (error) { logger.error("Error fetching global leaderboard", error); res.status(500).json({ success: false, msg: "Server error fetching global leaderboard", error: error.message }); } }); /** * @route GET /api/leaderboard/weekly * @desc Get weekly leaderboard * @access Public * @query limit (default 100), offset (default 0) */ router.get("/weekly", getCacheMiddleware(300), async (req, res) => { try { const limit = Math.min(parseInt(req.query.limit) || 100, 500); const offset = parseInt(req.query.offset) || 0; logger.info("Fetching weekly leaderboard", { limit, offset }); const leaderboard = await gamificationService.getWeeklyLeaderboard(limit, offset); res.json({ success: true, count: leaderboard.length, limit, offset, timeframe: "week", data: leaderboard }); } catch (error) { logger.error("Error fetching weekly leaderboard", error); res.status(500).json({ success: false, msg: "Server error fetching weekly leaderboard", error: error.message }); } }); /** * @route GET /api/leaderboard/monthly * @desc Get monthly leaderboard * @access Public * @query limit (default 100), offset (default 0) */ router.get("/monthly", getCacheMiddleware(300), async (req, res) => { try { const limit = Math.min(parseInt(req.query.limit) || 100, 500); const offset = parseInt(req.query.offset) || 0; logger.info("Fetching monthly leaderboard", { limit, offset }); const leaderboard = await gamificationService.getMonthlyLeaderboard(limit, offset); res.json({ success: true, count: leaderboard.length, limit, offset, timeframe: "month", data: leaderboard }); } catch (error) { logger.error("Error fetching monthly leaderboard", error); res.status(500).json({ success: false, msg: "Server error fetching monthly leaderboard", error: error.message }); } }); /** * @route GET /api/leaderboard/friends * @desc Get friends leaderboard (requires auth) * @access Private * @query limit (default 100), offset (default 0) */ router.get("/friends", auth, getCacheMiddleware(300), async (req, res) => { try { const limit = Math.min(parseInt(req.query.limit) || 100, 500); const offset = parseInt(req.query.offset) || 0; const userId = req.user.id; logger.info("Fetching friends leaderboard", { userId, limit, offset }); const leaderboard = await gamificationService.getFriendsLeaderboard(userId, limit, offset); res.json({ success: true, count: leaderboard.length, limit, offset, data: leaderboard }); } catch (error) { logger.error("Error fetching friends leaderboard", error); res.status(500).json({ success: false, msg: "Server error fetching friends leaderboard", error: error.message }); } }); /** * @route GET /api/leaderboard/user/:userId * @desc Get user's rank and position in leaderboard * @access Public */ router.get("/user/:userId", getCacheMiddleware(300), async (req, res) => { try { const { userId } = req.params; const timeframe = req.query.timeframe || "all"; // all, week, month logger.info("Fetching user leaderboard position", { userId, timeframe }); const userPosition = await gamificationService.getUserLeaderboardPosition(userId, timeframe); if (!userPosition) { return res.status(404).json({ success: false, msg: "User not found or has no points" }); } res.json({ success: true, data: userPosition }); } catch (error) { logger.error("Error fetching user leaderboard position", error); res.status(500).json({ success: false, msg: "Server error fetching user position", error: error.message }); } }); /** * @route GET /api/leaderboard/stats * @desc Get leaderboard statistics * @access Public */ router.get("/stats", getCacheMiddleware(300), async (req, res) => { try { logger.info("Fetching leaderboard statistics"); const stats = await gamificationService.getLeaderboardStats(); res.json({ success: true, data: stats }); } catch (error) { logger.error("Error fetching leaderboard statistics", error); res.status(500).json({ success: false, msg: "Server error fetching leaderboard statistics", error: error.message }); } }); module.exports = router;