const express = require('express'); const router = express.Router(); const path = require('path'); const fs = require('fs'); const multer = require('multer'); const sharp = require('sharp'); const User = require('../models/User'); const Asset = require('../models/Asset'); const Scene = require('../models/Scene'); const Hotspot = require('../models/Hotspot'); const { protect } = require('../middlewares/authMiddleware'); const { ROLE_QUOTAS } = require('../middlewares/quotaMiddleware'); const uploadDir = process.env.UPLOAD_DIR ? path.resolve(process.env.UPLOAD_DIR) : path.join(__dirname, '../uploads'); const upload = multer({ dest: path.join(uploadDir, 'temp') }); // @route GET /api/users/search router.get('/search', protect, async (req, res) => { const query = req.query.q; if (!query || query.length < 2) return res.json([]); try { const users = await User.find({ _id: { $ne: req.user._id }, $or: [{ username: { $regex: query, $options: 'i' } }, { email: { $regex: query, $options: 'i' } }] }).select('username email').limit(10); res.json(users); } catch (error) { res.status(500).json({ message: error.message }); } }); // @route GET /api/me/scenes // @desc Lấy danh sách các cảnh do chính người dùng hiện tại tạo router.get('/scenes', protect, async (req, res) => { try { const scenes = await Scene.find({ createdBy: req.user._id }) .populate('createdBy', 'username') .populate('assetId') .select('+views') // Đảm bảo lấy được trường views để hiển thị thống kê .sort({ createdAt: -1 }) .lean(); // Kiểm tra xem mỗi scene có phải là scene con (được trỏ tới bởi hotspot khác) hay không // Điều này giúp Frontend quyết định quyền thay đổi Privacy for (let i = 0; i < scenes.length; i++) { const isChild = await Hotspot.exists({ target_scene_id: scenes[i]._id }); scenes[i].isChildScene = !!isChild; } res.json(scenes); } catch (error) { res.status(500).json({ message: error.message }); } }); // @route GET /api/me/profile router.get('/profile', protect, async (req, res) => { try { const user = await User.findById(req.user._id).select('-password').lean(); const usage = await Asset.aggregate([{ $match: { uploadedBy: req.user._id } }, { $group: { _id: null, total: { $sum: "$fileSize" } } }]); const currentUsage = usage.length > 0 ? usage[0].total : 0; res.json({ ...user, storage: { used: currentUsage, quota: ROLE_QUOTAS[user.role] || ROLE_QUOTAS['Thành viên'] } }); } catch (error) { res.status(500).json({ message: error.message }); } }); // @route PUT /api/me/profile router.put('/profile', protect, upload.single('avatar'), async (req, res) => { try { const user = await User.findById(req.user._id); const { fullName, email, username, password } = req.body; if (fullName) user.fullName = fullName; if (email) user.email = email; if (username) user.username = username; if (password && password.trim() !== '') user.password = password; if (req.file) { if (user.avatarUrl && user.avatarUrl.includes('avatar_')) { const oldPath = path.join(uploadDir, user.avatarUrl.split('/').pop()); await fs.promises.unlink(oldPath).catch(() => {}); } const avatarName = `avatar_${user._id}${path.extname(req.file.originalname)}`; const avatarPath = path.join(uploadDir, avatarName); await sharp(req.file.path).resize(200, 200).toFile(avatarPath); user.avatarUrl = `/api/assets/view_avatar/${avatarName}`; await fs.promises.unlink(req.file.path).catch(() => {}); } await user.save({ validateBeforeSave: false }); res.json({ message: 'Hồ sơ đã được cập nhật', user: { id: user._id, username: user.username, role: user.role } }); } catch (error) { res.status(400).json({ message: error.message }); } }); module.exports = router;