const { ensureConversationExists, saveMessage } = require('../services');
const clients = new Map();
const rooms = new Map();

exports.handleSocketIoConnection = (socket, io) => {
	// Listen for incoming 'join' messages to connect a user to a chat
	socket.on('join', (data) => {
		const { userId, convoId } = data;
		addClient(socket, userId, convoId);
		socket.emit('joined', { message: 'Connected to chat!' });
	});

	// Listen for incoming 'message' events
	socket.on('message', (data) => {
		const { userId, convoId, messageContent, receiverId } = data;

		// Validate message payload
		if (!userId || !messageContent || !convoId) {
			return socket.emit('error', { message: 'Invalid payload' });
		}

		// Ensure the conversation exists and broadcast the message
		ensureConversationExists(userId, receiverId, convoId)
			.then((newConvoId) => {
				// Broadcast the message to all users in the room
				broadcastMessage(io, newConvoId, userId, messageContent);
				return saveMessage(newConvoId, userId, messageContent);
			})
			.then(() => {
				// Respond to the sender that the message was successfully sent
				socket.emit('success', { message: 'Message sent successfully!' });
			})
			.catch((error) => {
				// Handle errors
				console.error('Error handling message:', error);
				socket.emit('error', { message: error.message });
			});
	});

	// Handle disconnections
	socket.on('disconnect', () => {
		removeClient(socket);
	});
};

// Add a client to the map and room
const addClient = (socket, userId, convoId) => {
	clients.set(userId, socket);

	// Create room if it doesn't exist
	if (!rooms.has(convoId)) {
		rooms.set(convoId, new Set());
	}

	// Add user to the room
	rooms.get(convoId).add(userId);
	console.log(`User ${userId} joined conversation ${convoId}.`);
	console.log(`Current clients in room ${convoId}:`, rooms.get(convoId));
};

// Remove a client when they disconnect
const removeClient = (socket) => {
	for (const [userId, client] of clients.entries()) {
		if (client === socket) {
			// Remove client from all rooms
			for (const [convoId, room] of rooms.entries()) {
				room.delete(userId);
				if (room.size === 0) {
					rooms.delete(convoId);  // Clean up room if empty
				}
			}

			clients.delete(userId);  // Remove client from map
			console.log(`User ${userId} disconnected.`);
			break;
		}
	}
};

// Broadcast a new message to all users in a conversation room
const broadcastMessage = (io, convoId, senderId, messageContent) => {
	const payload = {
		type: 'newMessage',
		convoId,
		senderId,
		messageContent,
		timestamp: new Date().toISOString(),
	};

	console.log('Broadcasting message:', payload);

	const room = rooms.get(convoId);
	if (room) {
		// Send the message to all clients in the room
		room.forEach((userId) => {
			const client = clients.get(userId);
			if (client && client.connected) {
				console.log(`Sending message to ${userId}`);
				client.emit('newMessage', payload); // Emit 'newMessage' event to client
			}
		});
	} else {
		console.log(`No clients found in room ${convoId}`);
	}
};
