const { ValidationError, ConflictError } = require('../shared/errors'); const { Op } = require('sequelize'); class FriendsService { constructor({ friendshipsRepository, friendRequestsRepository, usersRepository, sequelize, }) { this.friendshipsRepository = friendshipsRepository; this.friendRequestsRepository = friendRequestsRepository; this.usersRepository = usersRepository; this.sequelize = sequelize; } async getFriendsByUserId(userId) { return await this.friendshipsRepository.findByUserId(userId); } async getPendingRequests(userId) { return await this.friendRequestsRepository.findPendingByUserId(userId); } async sendFriendRequest(fromUserId, identifier) { let toUser; if (typeof identifier === 'number' || !isNaN(identifier)) { toUser = await this.usersRepository.findById(parseInt(identifier, 10)); } else { toUser = await this.usersRepository.findOne({ [Op.or]: [{ name: identifier }, { email: identifier }], }); if (!toUser) { throw new ValidationError( 'User not found with provided name or email' ); } } if (toUser.id === fromUserId) { throw new ValidationError('Cannot send friend request to yourself'); } const friendshipExists = await this.friendshipsRepository.exists( fromUserId, toUser.id ); if (friendshipExists) { throw new ConflictError('You are already friends with this user'); } const existingRequest = await this.friendRequestsRepository.findExisting( fromUserId, toUser.id ); if (existingRequest) { throw new ConflictError('Friend request already exists'); } return await this.friendRequestsRepository.create(fromUserId, toUser.id); } async acceptFriendRequest(requestId, userId) { const request = await this.friendRequestsRepository.findById(requestId); if (request.toUserId !== userId) { throw new ValidationError('You can only accept requests sent to you'); } if (request.status !== 'PENDING') { throw new ValidationError('This request has already been processed'); } const t = await this.sequelize.transaction(); try { await this.friendRequestsRepository.updateStatus(requestId, 'ACCEPTED'); await this.friendshipsRepository.create(request.fromUserId, request.toUserId); await this.friendRequestsRepository.delete(requestId); await t.commit(); return { message: 'Friend request accepted successfully' }; } catch (error) { await t.rollback(); throw error; } } async rejectFriendRequest(requestId, userId) { const request = await this.friendRequestsRepository.findById(requestId); if (request.toUserId !== userId && request.fromUserId !== userId) { throw new ValidationError('You can only manage your own requests'); } await this.friendRequestsRepository.delete(requestId); return { message: 'Friend request rejected successfully' }; } } module.exports = FriendsService;