const express = require("express"); const mongoose = require("mongoose"); const Reward = require("../models/Reward"); const User = require("../models/User"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createRewardValidation, rewardIdValidation, } = require("../middleware/validators/rewardValidator"); const { paginate, buildPaginatedResponse } = require("../middleware/pagination"); const { deductRewardPoints } = require("../services/gamificationService"); const router = express.Router(); // Get all rewards (with pagination) router.get( "/", paginate, asyncHandler(async (req, res) => { const { skip, limit, page } = req.pagination; const rewards = await Reward.find() .sort({ cost: 1 }) .skip(skip) .limit(limit); const totalCount = await Reward.countDocuments(); res.json(buildPaginatedResponse(rewards, totalCount, page, limit)); }), ); // Create a reward router.post( "/", auth, createRewardValidation, asyncHandler(async (req, res) => { const { name, description, cost, isPremium } = req.body; const newReward = new Reward({ name, description, cost, isPremium, }); const reward = await newReward.save(); res.json(reward); }), ); // Redeem a reward router.post( "/redeem/:id", auth, rewardIdValidation, asyncHandler(async (req, res) => { const session = await mongoose.startSession(); session.startTransaction(); try { const reward = await Reward.findById(req.params.id).session(session); if (!reward) { await session.abortTransaction(); session.endSession(); return res.status(404).json({ msg: "Reward not found" }); } const user = await User.findById(req.user.id).session(session); if (!user) { await session.abortTransaction(); session.endSession(); return res.status(404).json({ msg: "User not found" }); } if (user.points < reward.cost) { await session.abortTransaction(); session.endSession(); return res.status(400).json({ msg: "Not enough points" }); } if (reward.isPremium && !user.isPremium) { await session.abortTransaction(); session.endSession(); return res.status(403).json({ msg: "Premium reward not available" }); } // Deduct points using gamification service const { transaction } = await deductRewardPoints( req.user.id, reward._id, reward.cost, session ); await session.commitTransaction(); session.endSession(); res.json({ msg: "Reward redeemed successfully", pointsDeducted: Math.abs(transaction.amount), newBalance: transaction.balanceAfter, }); } catch (err) { await session.abortTransaction(); session.endSession(); throw err; } }), ); module.exports = router;