const couchdbService = require("../services/couchdbService"); class Reward { static async create(rewardData) { const reward = { _id: `reward_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: "reward", name: rewardData.name, description: rewardData.description, cost: rewardData.cost, isPremium: rewardData.isPremium || false, isActive: rewardData.isActive !== undefined ? rewardData.isActive : true, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; return await couchdbService.create(reward); } static async findById(rewardId) { return await couchdbService.getById(rewardId); } static async find(query = {}, options = {}) { const defaultQuery = { type: "reward", ...query }; return await couchdbService.find({ selector: defaultQuery, ...options }); } static async findOne(query) { const rewards = await this.find(query, { limit: 1 }); return rewards[0] || null; } static async update(rewardId, updateData) { const reward = await this.findById(rewardId); if (!reward) { throw new Error("Reward not found"); } const updatedReward = { ...reward, ...updateData, updatedAt: new Date().toISOString() }; return await couchdbService.update(rewardId, updatedReward); } static async delete(rewardId) { return await couchdbService.delete(rewardId); } static async findByCostRange(minCost, maxCost) { return await couchdbService.find({ selector: { type: "reward", cost: { $gte: minCost, $lte: maxCost } }, sort: [{ cost: "asc" }] }); } static async findByPremiumStatus(isPremium) { return await this.find({ isPremium }); } static async getActiveRewards() { return await this.find({ isActive: true }); } static async getPremiumRewards() { return await this.find({ isPremium: true, isActive: true }); } static async getRegularRewards() { return await this.find({ isPremium: false, isActive: true }); } static async getAllPaginated(page = 1, limit = 10) { const skip = (page - 1) * limit; const rewards = await couchdbService.find({ selector: { type: "reward" }, sort: [{ cost: "asc" }], skip, limit }); // Get total count const totalCount = await couchdbService.find({ selector: { type: "reward" }, fields: ["_id"] }); return { rewards, pagination: { page, limit, totalCount: totalCount.length, totalPages: Math.ceil(totalCount.length / limit) } }; } static async redeemReward(userId, rewardId) { const reward = await this.findById(rewardId); if (!reward) { throw new Error("Reward not found"); } if (!reward.isActive) { throw new Error("Reward is not available"); } const user = await couchdbService.findUserById(userId); if (!user) { throw new Error("User not found"); } if (user.points < reward.cost) { throw new Error("Not enough points"); } if (reward.isPremium && !user.isPremium) { throw new Error("Premium reward not available"); } // Deduct points using couchdbService method const updatedUser = await couchdbService.updateUserPoints( userId, -reward.cost, `Redeemed reward: ${reward.name}`, { entityType: 'Reward', entityId: rewardId, entityName: reward.name } ); // Create redemption record const redemption = { _id: `redemption_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: "reward_redemption", user: { userId: userId, name: user.name }, reward: { rewardId: rewardId, name: reward.name, description: reward.description, cost: reward.cost }, pointsDeducted: reward.cost, balanceAfter: updatedUser.points, redeemedAt: new Date().toISOString() }; await couchdbService.create(redemption); return { redemption, pointsDeducted: reward.cost, newBalance: updatedUser.points }; } static async getUserRedemptions(userId, limit = 20) { return await couchdbService.find({ selector: { type: "reward_redemption", "user.userId": userId }, sort: [{ redeemedAt: "desc" }], limit }); } static async getRewardStats(rewardId) { const redemptions = await couchdbService.find({ selector: { type: "reward_redemption", "reward.rewardId": rewardId } }); return { totalRedemptions: redemptions.length, totalPointsSpent: redemptions.reduce((sum, r) => sum + r.pointsDeducted, 0), lastRedeemed: redemptions.length > 0 ? redemptions[0].redeemedAt : null }; } static async getCatalogStats() { const rewards = await this.getActiveRewards(); const premium = await this.getPremiumRewards(); const regular = await this.getRegularRewards(); return { totalRewards: rewards.length, premiumRewards: premium.length, regularRewards: regular.length, averageCost: rewards.reduce((sum, r) => sum + r.cost, 0) / rewards.length || 0, minCost: Math.min(...rewards.map(r => r.cost)), maxCost: Math.max(...rewards.map(r => r.cost)) }; } static async searchRewards(searchTerm, options = {}) { const query = { selector: { type: "reward", isActive: true, $or: [ { name: { $regex: searchTerm, $options: "i" } }, { description: { $regex: searchTerm, $options: "i" } } ] }, ...options }; return await couchdbService.find(query); } // Migration helper static async migrateFromMongo(mongoReward) { const rewardData = { name: mongoReward.name, description: mongoReward.description, cost: mongoReward.cost, isPremium: mongoReward.isPremium || false, isActive: true }; return await this.create(rewardData); } // Bulk operations for admin static async bulkCreate(rewardsData) { const rewards = rewardsData.map(data => ({ _id: `reward_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, type: "reward", name: data.name, description: data.description, cost: data.cost, isPremium: data.isPremium || false, isActive: data.isActive !== undefined ? data.isActive : true, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() })); return await couchdbService.bulkDocs(rewards); } static async toggleActiveStatus(rewardId) { const reward = await this.findById(rewardId); if (!reward) { throw new Error("Reward not found"); } return await this.update(rewardId, { isActive: !reward.isActive }); } } module.exports = Reward;