const User = require('../models/User'); // Нам нужна модель User const Conversation = require('../models/Conversation'); // Добавляем модель Conversation // @desc Лайкнуть пользователя // @route POST /api/actions/like/:userId // @access Private const likeUser = async (req, res, next) => { const likedUserId = req.params.userId; // ID пользователя, которого лайкают const currentUserId = req.user._id; // ID текущего пользователя (из protect middleware) console.log(`[ACTION_CTRL] Пользователь ${currentUserId} лайкает пользователя ${likedUserId}`); try { // 0. Проверка, не лайкает ли пользователь сам себя if (currentUserId.equals(likedUserId)) { const error = new Error('Вы не можете лайкнуть самого себя.'); error.statusCode = 400; throw error; } // 1. Найти обоих пользователей const currentUser = await User.findById(currentUserId); const likedUser = await User.findById(likedUserId); if (!currentUser || !likedUser) { const error = new Error('Один из пользователей не найден.'); error.statusCode = 404; throw error; } // 2. Проверить, не был ли этот пользователь уже лайкнут или пропущен текущим пользователем if (currentUser.liked.includes(likedUserId)) { console.log(`[ACTION_CTRL] Пользователь ${likedUserId} уже был лайкнут пользователем ${currentUserId}`); // Можно вернуть информацию о существующем лайке или просто успешный ответ return res.status(200).json({ message: 'Пользователь уже был лайкнут ранее.', isMatch: currentUser.matches.includes(likedUserId) }); } if (currentUser.passed.includes(likedUserId)) { // Если пользователь был ранее пропущен, убираем его из passed и продолжаем как обычный лайк currentUser.passed.pull(likedUserId); console.log(`[ACTION_CTRL] Пользователь ${likedUserId} был ранее пропущен, теперь лайкнут пользователем ${currentUserId}`); } // 3. Добавить likedUserId в массив 'liked' текущего пользователя currentUser.liked.addToSet(likedUserId); // addToSet добавляет, только если элемента еще нет // 4. Проверить на взаимный лайк (мэтч) let isMatch = false; let conversationId = null; // Инициализируем conversationId // Проверяем, лайкал ли 'likedUser' текущего пользователя ('currentUser') if (likedUser.liked.includes(currentUserId)) { isMatch = true; // Если мэтч, добавляем друг друга в массивы 'matches' currentUser.matches.addToSet(likedUserId); likedUser.matches.addToSet(currentUserId); await likedUser.save(); // Сохраняем изменения для likedUser console.log(`[ACTION_CTRL] !!! МЭТЧ !!! между ${currentUserId} и ${likedUserId}`); // Автоматическое создание или получение диалога при мэтче try { let conversation = await Conversation.findOne({ participants: { $all: [currentUserId, likedUserId] } }); if (!conversation) { console.log(`[ACTION_CTRL] Создание нового диалога для мэтча между ${currentUserId} и ${likedUserId}`); conversation = new Conversation({ participants: [currentUserId, likedUserId] }); await conversation.save(); console.log(`[ACTION_CTRL] Новый диалог создан с ID: ${conversation._id}`); } else { console.log(`[ACTION_CTRL] Диалог для мэтча между ${currentUserId} и ${likedUserId} уже существует: ${conversation._id}`); } conversationId = conversation._id; // Сохраняем ID диалога } catch (convError) { console.error(`[ACTION_CTRL] Ошибка при создании/получении диалога для мэтча:`, convError.message); // Не прерываем основной ответ из-за ошибки создания чата, // но логируем. В реальном приложении здесь могла бы быть // более сложная обработка или уведомление администратора. } // TODO: Здесь можно будет добавить логику для отправки уведомления о мэтче } await currentUser.save(); // Сохраняем изменения для currentUser const responseJson = { message: isMatch ? 'Это мэтч! Вы понравились друг другу!' : 'Лайк успешно поставлен.', isMatch: isMatch, }; if (isMatch && conversationId) { responseJson.conversationId = conversationId; } res.status(200).json(responseJson); } catch (error) { console.error(`[ACTION_CTRL] Ошибка при лайке пользователя ${likedUserId} пользователем ${currentUserId}:`, error.message); // Если statusCode не установлен ошибкой, errorHandler поставит 500 // Для ошибок типа "не найден" мы уже ставим 404 next(error); } }; // @desc Пропустить/дизлайкнуть пользователя // @route POST /api/actions/pass/:userId // @access Private const passUser = async (req, res, next) => { const passedUserId = req.params.userId; // ID пользователя, которого пропускают const currentUserId = req.user._id; // ID текущего пользователя console.log(`[ACTION_CTRL] Пользователь ${currentUserId} пропускает пользователя ${passedUserId}`); try { // 0. Проверка, не пропускает ли пользователь сам себя if (currentUserId.equals(passedUserId)) { const error = new Error('Вы не можете пропустить самого себя.'); error.statusCode = 400; throw error; } const currentUser = await User.findById(currentUserId); const userToPass = await User.findById(passedUserId); // Проверяем, что такой пользователь существует if (!currentUser || !userToPass) { const error = new Error('Один из пользователей не найден.'); error.statusCode = 404; throw error; } // 1. Добавить passedUserId в массив 'passed' текущего пользователя currentUser.passed.addToSet(passedUserId); // 2. Если этот пользователь был ранее лайкнут, убрать его из лайков // (на случай, если пользователь передумал, хотя UI обычно не дает так сделать без "анлайка") if (currentUser.liked.includes(passedUserId)) { currentUser.liked.pull(passedUserId); // Также нужно проверить, не был ли это мэтч, и если да, то убрать из мэтчей у обоих if (currentUser.matches.includes(passedUserId)) { currentUser.matches.pull(passedUserId); userToPass.matches.pull(currentUserId); await userToPass.save(); // Сохраняем изменения для другого пользователя console.log(`[ACTION_CTRL] Мэтч между ${currentUserId} и ${passedUserId} был разорван из-за пропуска.`); } } await currentUser.save(); res.status(200).json({ message: 'Пользователь успешно пропущен.', // passed: currentUser.passed }); } catch (error) { console.error(`[ACTION_CTRL] Ошибка при пропуске пользователя ${passedUserId} пользователем ${currentUserId}:`, error.message); next(error); } }; module.exports = { likeUser, passUser, };