const router = require('express').Router(); const User = require('../models/User'); const Transaction = require('../models/Transaction'); const Asset = require('../models/Asset'); const verify = require('../utils/verifyToken'); const { generateKUS } = require('../utils/kusGenerator'); const StrikeHistory = require('../models/StrikeHistory'); const AllTransaction = require('../models/AllTransaction'); const logTransaction = require('../utils/ledgerLogger'); const { sendToUser } = require('../utils/sendPush'); const { runStrike } = require('../services/strikeEngine'); // MIDDLEWARE: Check if Admin const verifyAdmin = async (req, res, next) => { const user = await User.findById(req.user._id); if (user.role !== 'admin') return res.status(403).send("ACCESS DENIED"); next(); }; // 1. DASHBOARD STATS (The Top Grid) router.get('/stats', verify, verifyAdmin, async (req, res) => { try { const today = new Date(); today.setHours(0,0,0,0); // Calculate Today's Sales const dailySales = await Transaction.aggregate([ { $match: { timestamp: { $gte: today }, status: 'Verified' } }, { $group: { _id: null, total: { $sum: "$amount" } } } ]); const pendingCount = await Transaction.countDocuments({ status: 'Pending' }); const userCount = await User.countDocuments(); const bannedCount = await User.countDocuments({ ban_strikes: { $gte: 3 } }); res.json({ sales: dailySales[0]?.total || 0, pending: pendingCount, users: userCount, banned: bannedCount }); } catch (err) { res.status(500).send("Stats Error"); } }); // 2. GET PENDING TRANSACTIONS (The Worklist) router.get('/transactions/pending', verify, verifyAdmin, async (req, res) => { try { // Populate user name to see who is paying const txs = await Transaction.find({ status: 'Pending' }) .populate('user_id', 'name email ban_strikes') .sort({ timestamp: -1 }); res.json(txs); } catch (err) { res.status(500).send("Fetch Error"); } }); // 3. ACTION: APPROVE PAYMENT (Manual Verification) router.post('/approve', verify, verifyAdmin, async (req, res) => { try { const { transactionId } = req.body; const tx = await Transaction.findById(transactionId); if (!tx || tx.status !== 'Pending') return res.status(400).send("Invalid Transaction"); // 1. Generate Asset const newKUS = await generateKUS(tx.tier); // 3. Update Tx tx.status = 'Verified'; await tx.save(); await Asset.findByIdAndUpdate(tx.asset_id, { status: 'Held' }); await logTransaction(tx.user_id, 'DEPOSIT', tx.amount, 'INR', `Deposit Verified (Tier: ${tx.tier})`); // 4. Referral Logic (Simplified) const assetCount = await Asset.countDocuments({ owner_id: tx.user_id }); if (assetCount === 1) { const user = await User.findById(tx.user_id); if (user.referred_by) { const referrer = await User.findOne({ referral_code: user.referred_by }); if (referrer) { let reward = 0; if (tx.tier === 'Silver') reward = 100; if (tx.tier === 'Gold') reward = 150; if (tx.tier === 'Platinum') reward = 250; let userReward = 0; if (tx.tier === 'Silver') reward = 50; if (tx.tier === 'Gold') reward = 75; if (tx.tier === 'Platinum') reward = 125; referrer.points += reward; await referrer.save(); user.points += userReward; await user.save(); await logTransaction(referrer._id, 'REFERRAL_BONUS', reward, 'INR', `Referral Bonus Tier: ${tx.tier}`); await sendToUser(referrer._id, "Referral Bonus Credited", `${reward} points credited to your account.`, "/profile"); await logTransaction(user._id, 'REFERRAL_BONUS', userReward, 'INR', `Referral Bonus Tier: ${tx.tier}`); await sendToUser(user._id, "Referral Bonus Credited", `${userReward} points credited to your account.`, "/profile"); console.log(`[Referral] ${reward} points added to ${referrer.name}`); } } } await sendToUser(tx.user_id, "✅ Deposit Verified", `₹${tx.amount} added to your assets.`, "/profile"); res.json({ success: true, message: "Payment Verified & Asset Assigned" }); } catch (err) { res.status(500).send("Approval Error"); } }); // 4. ACTION: REJECT & STRIKE (The Ban Hammer) router.post('/reject', verify, verifyAdmin, async (req, res) => { try { const { transactionId } = req.body; const tx = await Transaction.findById(transactionId); if (!tx) return res.status(404).send("Tx not found"); // 1. Mark Failed tx.status = 'Failed'; tx.rejection_reason = "Invalid UTR / Payment Not Received"; // Static Reason await tx.save(); await Asset.findByIdAndDelete(tx.asset_id); // 2. Add Strike to User const user = await User.findById(tx.user_id); user.ban_strikes += 1; await user.save(); res.json({ success: true, message: `Transaction Rejected. User Strikes: ${user.ban_strikes}/3` }); await sendToUser(tx.user_id, "❌ Deposit Failed", "Your UTR was rejected. Check Activity Log.", "/profile"); } catch (err) { res.status(500).send("Reject Error"); } }); module.exports = router; // ADD STRIKE (Called when Admin rejects a UTR) router.post('/strike-user', verify, verifyAdmin, async (req, res) => { const { userId } = req.body; const user = await User.findById(userId); user.ban_strikes += 1; await user.save(); if (user.ban_strikes >= 3) { // Optional: Send email notification "You are banned" console.log(`User ${user.name} is now BANNED.`); } res.send({ message: `Strike added. Total: ${user.ban_strikes}/3` }); }); // 5. GET ALL USERS (Manage Users) router.get('/users', verify, verifyAdmin, async (req, res) => { const users = await User.find().select('-password').sort({ createdAt: -1 }); res.json(users); }); // 6. GET ALL ASSETS (Asset Inventory) router.get('/assets', verify, verifyAdmin, async (req, res) => { const assets = await Asset.find({ status: 'Held' }).populate('owner_id', 'name email'); res.json(assets); }); // 7. GET WINNER HISTORY (Last 60 Days) router.get('/history', verify, verifyAdmin, async (req, res) => { const history = await StrikeHistory.find().sort({ date: -1 }).limit(60).populate('winners.user_id', 'name'); res.json(history); }); // 8. LEDGER (All Transactions) router.get('/ledger', verify, verifyAdmin, async (req, res) => { const txs = await Transaction.find().populate('user_id', 'name').sort({ timestamp: -1 }).limit(100); res.json(txs); }); // 9. MANUAL STRIKE TRIGGER router.post('/trigger-strike', verify, verifyAdmin, async (req, res) => { // SECURITY: Ensure you export the logic function properly from jobs/strike.js // For now, let's assume you moved the logic to a controller function called `executeStrikeLogic` // await executeStrikeLogic(); startStrike(); res.json({ message: "Strike Triggered Manually" }); }); router.post('/manual-strike', verify, verifyAdmin, async (req, res) => { try { await runStrike({ triggeredBy: "ADMIN" }); res.json({ success: true }); } catch (err) { if (err.message === "STRIKE_ALREADY_EXECUTED") { return res.status(400).json("Strike already executed today"); } res.status(500).json("Strike failed"); } }); // 10. UNBAN USER router.post('/unban', verify, verifyAdmin, async (req, res) => { const { userId } = req.body; await User.findByIdAndUpdate(userId, { ban_strikes: 0 }); res.json({ message: "User Unbanned" }); }); // WITHDRAWAL REQUESTS (Fixes 404) router.get('/withdrawals', verify, verifyAdmin, async (req, res) => { const requests = await Transaction.find({ status: 'Pending_Withdrawal' }) .populate('user_id', 'name email upi_id'); res.json(requests); }); // CONFIRM WITHDRAWAL PAID router.post('/withdraw-confirm', verify, verifyAdmin, async (req, res) => { const { transactionId, adminUtr } = req.body; await Transaction.findByIdAndUpdate(transactionId, { status: 'Withdrawn', utr: adminUtr }); await sendToUser(tx.user_id, "💸 Payment Sent", "Your withdrawal has been processed via UPI.", "/profile"); res.json({ success: true }); }); router.get('/global-ledger', verify, verifyAdmin, async (req, res) => { try { // Support Filtering via Query Params const { type, email } = req.query; let query = {}; if (type && type !== 'ALL') query.type = type; if (email) { const user = await User.findOne({ email }); if (user) query.user_id = user._id; } const history = await AllTransaction.find(query) .populate('user_id', 'name email') .sort({ timestamp: -1 }) .limit(200); // Limit to prevent crashing res.json(history); } catch (err) { res.status(500).send("Error"); } }); // REJECT WITHDRAWAL (Admin Action) router.post('/withdraw-reject', verify, verifyAdmin, async (req, res) => { const { transactionId, reason } = req.body; const tx = await Transaction.findById(transactionId); if (!tx) return res.status(404).send("Tx Not Found"); // 1. Refund the money to wallet const user = await User.findById(tx.user_id); user.wallet_balance += tx.amount; await user.save(); // 2. Update Transaction tx.status = 'Rejected_Withdrawal'; tx.rejection_reason = reason || "Admin Rejected Request"; await tx.save(); // 3. Log to Ledger (Refund) await logTransaction(user._id, 'REFUND', tx.amount, 'INR', `Withdrawal Rejected: ${reason}`); res.json({ success: true }); }); // 12. GET SINGLE USER DETAILS (Deep Dive) router.get('/user/:id', verify, verifyAdmin, async (req, res) => { try { const user = await User.findById(req.params.id).select('-password'); if (!user) return res.status(404).send("User not found"); // Fetch their assets const assets = await Asset.find({ owner_id: user._id }); // Fetch their transactions (Last 50) const txs = await Transaction.find({ user_id: user._id }).sort({ timestamp: -1 }).limit(50); res.json({ user, assets, transactions: txs }); } catch (err) { res.status(500).send("Error fetching user details"); } }); // 13. UPDATE USER (Edit Details) router.put('/user/:id', verify, verifyAdmin, async (req, res) => { try { const { name, email, wallet_balance, points, ban_strikes } = req.body; await User.findByIdAndUpdate(req.params.id, { name, email, wallet_balance, points, ban_strikes }); res.json({ success: true, message: "User Updated" }); } catch (err) { res.status(500).send("Update Failed"); } }); // 14. DELETE USER (Hard Delete) router.delete('/user/:id', verify, verifyAdmin, async (req, res) => { try { const userId = req.params.id; // 1. Delete User await User.findByIdAndDelete(userId); // 2. Delete Assets? (Optional: Keep them or burn them) await Asset.deleteMany({ owner_id: userId }); // 3. Transactions are usually kept for ledger integrity, // but if you want a clean wipe: // await Transaction.deleteMany({ user_id: userId }); res.json({ success: true, message: "User Deleted" }); } catch (err) { res.status(500).send("Delete Failed"); } }); module.exports = router;