const express = require("express"); const Reward = require("../models/Reward"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createRewardValidation, rewardIdValidation, } = require("../middleware/validators/rewardValidator"); const { paginate, buildPaginatedResponse } = require("../middleware/pagination"); const router = express.Router(); // Get all rewards (with pagination) router.get( "/", paginate, asyncHandler(async (req, res) => { const { page, limit } = req.pagination; const result = await Reward.getAllPaginated(page, limit); res.json(buildPaginatedResponse(result.rewards, result.pagination.totalCount, page, limit)); }), ); // Create a reward router.post( "/", auth, createRewardValidation, asyncHandler(async (req, res) => { const { name, description, cost, isPremium } = req.body; const reward = await Reward.create({ name, description, cost, isPremium, }); res.json(reward); }), ); // Redeem a reward router.post( "/redeem/:id", auth, rewardIdValidation, asyncHandler(async (req, res) => { const rewardId = req.params.id; const userId = req.user.id; try { const result = await Reward.redeemReward(userId, rewardId); res.json({ msg: "Reward redeemed successfully", pointsDeducted: result.pointsDeducted, newBalance: result.newBalance, redemption: result.redemption }); } catch (error) { if (error.message === "Reward not found") { return res.status(404).json({ msg: "Reward not found" }); } if (error.message === "Reward is not available") { return res.status(400).json({ msg: "Reward is not available" }); } if (error.message === "User not found") { return res.status(404).json({ msg: "User not found" }); } if (error.message === "Not enough points") { return res.status(400).json({ msg: "Not enough points" }); } if (error.message === "Premium reward not available") { return res.status(403).json({ msg: "Premium reward not available" }); } throw error; } }), ); // Get reward by ID router.get( "/:id", rewardIdValidation, asyncHandler(async (req, res) => { const reward = await Reward.findById(req.params.id); if (!reward) { return res.status(404).json({ msg: "Reward not found" }); } res.json(reward); }) ); // Update reward router.put( "/:id", auth, rewardIdValidation, createRewardValidation, asyncHandler(async (req, res) => { const { name, description, cost, isPremium, isActive } = req.body; const reward = await Reward.findById(req.params.id); if (!reward) { return res.status(404).json({ msg: "Reward not found" }); } const updateData = { name, description, cost, isPremium }; if (isActive !== undefined) { updateData.isActive = isActive; } const updatedReward = await Reward.update(req.params.id, updateData); res.json(updatedReward); }) ); // Delete reward router.delete( "/:id", auth, rewardIdValidation, asyncHandler(async (req, res) => { const reward = await Reward.findById(req.params.id); if (!reward) { return res.status(404).json({ msg: "Reward not found" }); } await Reward.delete(req.params.id); res.json({ msg: "Reward deleted successfully" }); }) ); // Get active rewards only router.get( "/active/list", asyncHandler(async (req, res) => { const rewards = await Reward.getActiveRewards(); res.json(rewards); }) ); // Get premium rewards router.get( "/premium/list", asyncHandler(async (req, res) => { const rewards = await Reward.getPremiumRewards(); res.json(rewards); }) ); // Get regular rewards router.get( "/regular/list", asyncHandler(async (req, res) => { const rewards = await Reward.getRegularRewards(); res.json(rewards); }) ); // Get rewards by cost range router.get( "/cost-range/:min/:max", asyncHandler(async (req, res) => { const { min, max } = req.params; const rewards = await Reward.findByCostRange(parseInt(min), parseInt(max)); res.json(rewards); }) ); // Get user's redemption history router.get( "/redemptions/user/:userId", auth, asyncHandler(async (req, res) => { const { userId } = req.params; const { limit = 20 } = req.query; // Only allow users to see their own redemption history if (userId !== req.user.id) { return res.status(403).json({ msg: "Access denied" }); } const redemptions = await Reward.getUserRedemptions(userId, parseInt(limit)); res.json(redemptions); }) ); // Get reward statistics router.get( "/stats/:id", rewardIdValidation, asyncHandler(async (req, res) => { const stats = await Reward.getRewardStats(req.params.id); res.json(stats); }) ); // Get catalog statistics router.get( "/catalog/stats", auth, asyncHandler(async (req, res) => { const stats = await Reward.getCatalogStats(); res.json(stats); }) ); // Search rewards router.get( "/search/:term", asyncHandler(async (req, res) => { const { term } = req.params; const { limit = 20 } = req.query; const rewards = await Reward.searchRewards(term, { limit: parseInt(limit) }); res.json(rewards); }) ); // Toggle reward active status router.patch( "/:id/toggle", auth, rewardIdValidation, asyncHandler(async (req, res) => { const updatedReward = await Reward.toggleActiveStatus(req.params.id); res.json(updatedReward); }) ); // Bulk create rewards (admin only) router.post( "/bulk", auth, asyncHandler(async (req, res) => { const { rewards } = req.body; if (!Array.isArray(rewards) || rewards.length === 0) { return res.status(400).json({ msg: "Invalid rewards array" }); } const result = await Reward.bulkCreate(rewards); res.json({ msg: `Created ${result.length} rewards`, rewards: result }); }) ); module.exports = router;