const Message = require('../models/Message'); const Conversation = require('../models/Conversation'); const { generateAIResponse } = require('../services/aiService'); const Joi = require('joi'); // Validation schema const sendMessageSchema = Joi.object({ conversationId: Joi.string().required(), content: Joi.string().min(1).max(10000).required() }); // Send message exports.sendMessage = async (req, res) => { try { // Validate input const { error } = sendMessageSchema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); } const { conversationId, content } = req.body; const userId = req.userId; // Verify conversation belongs to user const conversation = await Conversation.findOne({ _id: conversationId, userId }); if (!conversation) { return res.status(404).json({ error: 'Conversation not found' }); } // Create user message const userMessage = new Message({ conversationId, sender: 'user', content }); await userMessage.save(); // Update conversation conversation.messageCount += 1; conversation.lastMessageAt = new Date(); // Update title if it's the first message if (conversation.messageCount === 1) { conversation.title = content.substring(0, 50) + (content.length > 50 ? '...' : ''); } await conversation.save(); // Generate AI response const aiResponse = await generateAIResponse(content, conversationId); const assistantMessage = new Message({ conversationId, sender: 'assistant', content: aiResponse.content, metadata: aiResponse.metadata }); await assistantMessage.save(); // Update conversation message count conversation.messageCount += 1; conversation.lastMessageAt = new Date(); await conversation.save(); // Emit to socket if available const io = req.app.get('socketio'); if (io) { io.to(`user_${userId}`).emit('newMessage', { userMessage, assistantMessage }); } res.json({ userMessage, assistantMessage }); } catch (error) { console.error('Send message error:', error); res.status(500).json({ error: 'Internal server error' }); } }; // Get messages for a conversation exports.getMessages = async (req, res) => { try { const { conversationId } = req.params; const { page = 1, limit = 50 } = req.query; const userId = req.userId; // Verify conversation belongs to user const conversation = await Conversation.findOne({ _id: conversationId, userId }); if (!conversation) { return res.status(404).json({ error: 'Conversation not found' }); } // Get messages with pagination const messages = await Message.find({ conversationId }) .sort({ createdAt: 1 }) .limit(limit * 1) .skip((page - 1) * limit); const total = await Message.countDocuments({ conversationId }); res.json({ messages, pagination: { page: parseInt(page), limit: parseInt(limit), total, pages: Math.ceil(total / limit) } }); } catch (error) { console.error('Get messages error:', error); res.status(500).json({ error: 'Internal server error' }); } }; // Delete message exports.deleteMessage = async (req, res) => { try { const { messageId } = req.params; const userId = req.userId; // Find message and verify ownership const message = await Message.findById(messageId).populate({ path: 'conversationId', select: 'userId' }); if (!message) { return res.status(404).json({ error: 'Message not found' }); } if (message.conversationId.userId.toString() !== userId) { return res.status(403).json({ error: 'Unauthorized' }); } await Message.findByIdAndDelete(messageId); // Update conversation message count await Conversation.findByIdAndUpdate(message.conversationId._id, { $inc: { messageCount: -1 } }); res.json({ message: 'Message deleted successfully' }); } catch (error) { console.error('Delete message error:', error); res.status(500).json({ error: 'Internal server error' }); } };