const express = require('express'); const router = express.Router(); const jwt = require('jsonwebtoken'); const Admin = require('../models/Admin'); const adminAuth = require('../middleware/adminAuth'); const { body, validationResult } = require('express-validator'); // @route POST /api/admin/login // @desc Admin login // @access Public router.post('/login', [ body('username').notEmpty().trim().withMessage('Username or email is required'), body('password').notEmpty().withMessage('Password is required') ], async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, errors: errors.array() }); } const { username, password } = req.body; // Find admin by credentials const admin = await Admin.findByCredentials(username, password); // Generate JWT token const token = jwt.sign( { id: admin._id, email: admin.email, role: admin.role, isAdmin: true }, process.env.JWT_SECRET || 'your-secret-key', { expiresIn: '7d' } ); res.json({ success: true, message: 'Login successful', data: { token, admin: { id: admin._id, username: admin.username, email: admin.email, firstName: admin.firstName, lastName: admin.lastName, fullName: admin.fullName, avatar: admin.avatar, role: admin.role, permissions: admin.permissions } } }); } catch (error) { console.error('Admin login error:', error); res.status(401).json({ success: false, message: error.message || 'Invalid credentials' }); } }); // @route POST /api/admin/register // @desc Register new admin (super-admin only) // @access Private (Super Admin) router.post('/register', adminAuth, [ body('username').notEmpty().trim().toLowerCase().withMessage('Username is required'), body('email').isEmail().normalizeEmail().withMessage('Valid email is required'), body('password').isLength({ min: 8 }).withMessage('Password must be at least 8 characters'), body('firstName').notEmpty().trim().withMessage('First name is required'), body('lastName').notEmpty().trim().withMessage('Last name is required'), body('role').optional().isIn(['admin', 'editor', 'manager']).withMessage('Invalid role') ], async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, errors: errors.array() }); } // Check if requester is super admin const requester = await Admin.findById(req.admin.id); if (!requester || !requester.isSuperAdmin) { return res.status(403).json({ success: false, message: 'Only super admins can create new admin accounts' }); } const { username, email, password, firstName, lastName, role, permissions } = req.body; // Check if admin already exists const existingAdmin = await Admin.findOne({ $or: [{ username }, { email }] }); if (existingAdmin) { return res.status(400).json({ success: false, message: 'Admin with this username or email already exists' }); } // Create new admin const newAdmin = new Admin({ username, email, password, firstName, lastName, role: role || 'admin', permissions: permissions || ['manage_content', 'manage_rooms', 'manage_bookings'] }); await newAdmin.save(); res.status(201).json({ success: true, message: 'Admin account created successfully', data: { admin: { id: newAdmin._id, username: newAdmin.username, email: newAdmin.email, fullName: newAdmin.fullName, role: newAdmin.role, permissions: newAdmin.permissions } } }); } catch (error) { console.error('Admin registration error:', error); res.status(500).json({ success: false, message: 'Error creating admin account' }); } }); // @route GET /api/admin/me // @desc Get current admin profile // @access Private (Admin) router.get('/me', adminAuth, async (req, res) => { try { const admin = await Admin.findById(req.admin.id); if (!admin) { return res.status(404).json({ success: false, message: 'Admin not found' }); } res.json({ success: true, data: { admin } }); } catch (error) { console.error('Get admin profile error:', error); res.status(500).json({ success: false, message: 'Error fetching admin profile' }); } }); // @route PUT /api/admin/me // @desc Update current admin profile // @access Private (Admin) router.put('/me', adminAuth, [ body('firstName').optional().notEmpty().trim(), body('lastName').optional().notEmpty().trim(), body('email').optional().isEmail().normalizeEmail(), body('avatar').optional().isURL() ], async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, errors: errors.array() }); } const { firstName, lastName, email, avatar } = req.body; const updateFields = {}; if (firstName) updateFields.firstName = firstName; if (lastName) updateFields.lastName = lastName; if (email) updateFields.email = email; if (avatar) updateFields.avatar = avatar; const admin = await Admin.findByIdAndUpdate( req.admin.id, { $set: updateFields }, { new: true, runValidators: true } ); res.json({ success: true, message: 'Profile updated successfully', data: { admin } }); } catch (error) { console.error('Update admin profile error:', error); res.status(500).json({ success: false, message: 'Error updating profile' }); } }); // @route PUT /api/admin/change-password // @desc Change admin password // @access Private (Admin) router.put('/change-password', adminAuth, [ body('currentPassword').notEmpty().withMessage('Current password is required'), body('newPassword').isLength({ min: 8 }).withMessage('New password must be at least 8 characters') ], async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, errors: errors.array() }); } const { currentPassword, newPassword } = req.body; const admin = await Admin.findById(req.admin.id); if (!admin) { return res.status(404).json({ success: false, message: 'Admin not found' }); } // Verify current password const isMatch = await admin.comparePassword(currentPassword); if (!isMatch) { return res.status(401).json({ success: false, message: 'Current password is incorrect' }); } // Update password admin.password = newPassword; await admin.save(); res.json({ success: true, message: 'Password changed successfully' }); } catch (error) { console.error('Change password error:', error); res.status(500).json({ success: false, message: 'Error changing password' }); } }); // @route GET /api/admin/list // @desc Get all admins (super-admin only) // @access Private (Super Admin) router.get('/list', adminAuth, async (req, res) => { try { const requester = await Admin.findById(req.admin.id); if (!requester || !requester.isSuperAdmin) { return res.status(403).json({ success: false, message: 'Only super admins can view admin list' }); } const admins = await Admin.find().sort({ createdAt: -1 }); res.json({ success: true, data: { admins } }); } catch (error) { console.error('Get admin list error:', error); res.status(500).json({ success: false, message: 'Error fetching admin list' }); } }); // @route GET /api/admin/stats // @desc Get dashboard statistics // @access Private (Admin) router.get('/stats', adminAuth, async (req, res) => { try { const Booking = require('../models/Booking'); const Room = require('../models/Room'); const Guest = require('../models/Guest'); const BlogPost = require('../models/BlogPost'); const [ totalBookings, activeBookings, totalRooms, availableRooms, totalGuests, totalBlogPosts ] = await Promise.all([ Booking.countDocuments(), Booking.countDocuments({ status: { $in: ['Confirmed', 'Checked In'] } }), Room.countDocuments(), Room.countDocuments({ status: 'Available', isActive: true }), Guest.countDocuments(), BlogPost.countDocuments({ status: 'published' }) ]); // Get revenue for current month const startOfMonth = new Date(new Date().getFullYear(), new Date().getMonth(), 1); const revenueData = await Booking.aggregate([ { $match: { status: { $in: ['Confirmed', 'Checked In', 'Checked Out'] }, createdAt: { $gte: startOfMonth } } }, { $group: { _id: null, totalRevenue: { $sum: '$totalAmount' } } } ]); const monthlyRevenue = revenueData.length > 0 ? revenueData[0].totalRevenue : 0; res.json({ success: true, data: { stats: { bookings: { total: totalBookings, active: activeBookings }, rooms: { total: totalRooms, available: availableRooms }, guests: totalGuests, blogPosts: totalBlogPosts, revenue: { monthly: monthlyRevenue } } } }); } catch (error) { console.error('Get stats error:', error); res.status(500).json({ success: false, message: 'Error fetching statistics' }); } }); // Health check router.get('/health', (req, res) => { res.json({ success: true, service: 'admin', status: 'ok' }); }); module.exports = router;