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

exports.handleWebSocketConnection = (ws, wss) => {
	ws.on('message', (message) => {
		try {
			const data = JSON.parse(message);
			handleWebSocketMessage(ws, wss, data);
		} catch (error) {
			console.error('Invalid WebSocket message:', error.message);
		}
	});

	ws.on('close', () => {
		removeClient(ws);
	});
};

const handleWebSocketMessage = (ws, wss, data) => {
	const { type, userId, convoId, messageContent, receiverId } = data;

	switch (type) {
		case 'join':
			addClient(ws, userId, convoId);
			ws.send(JSON.stringify({ type: 'joined', message: 'Connected to chat!' }));
			break;

		case 'message':
			if (!userId || !messageContent || !convoId) {
				return ws.send(JSON.stringify({ type: 'error', message: 'Invalid payload' }));
			}

			ensureConversationExists(userId, receiverId, convoId)
				.then((newConvoId) => {
					broadcastMessage(wss, newConvoId, userId, messageContent);
					return saveMessage(newConvoId, userId, messageContent);
				})
				.then(() => {
					ws.send(JSON.stringify({ type: 'success', message: 'Message sent successfully!' }));
				})
				.catch((error) => {
					console.error('Error handling message:', error);
					ws.send(JSON.stringify({ type: 'error', message: error.message }));
				});
			break;

		default:
			ws.send(JSON.stringify({ type: 'error', message: 'Unknown message type' }));
	}
};

const addClient = (ws, userId, convoId) => {
	clients.set(userId, ws);

	if (!rooms.has(convoId)) {
		rooms.set(convoId, new Set());
	}

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

const removeClient = (ws) => {
	for (const [userId, client] of clients.entries()) {
		if (client === ws) {
			for (const [convoId, room] of rooms.entries()) {
				room.delete(userId);
				if (room.size === 0) {
					rooms.delete(convoId);
				}
			}

			clients.delete(userId);
			console.log(`User ${userId} disconnected.`);
			break;
		}
	}
};

const broadcastMessage = (wss, convoId, senderId, messageContent) => {
	const payload = JSON.stringify({
		type: 'newMessage',
		convoId,
		senderId,
		messageContent,
		timestamp: new Date().toISOString(),
	});

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

	const room = rooms.get(convoId);
	if (room) {
		room.forEach((userId) => {
			const client = clients.get(userId);
			if (client && client.readyState === WebSocket.OPEN) {
				console.log(`Sending message to ${userId}`);
				client.send(payload);
			}
		});
	} else {
		console.log(`No clients found in room ${convoId}`);
	}
};
