const { ValidationError } = require('../shared/errors'); const config = require('../config'); class BetsService { constructor({ betsRepository, usersRepository, dataStitchingService }) { this.betsRepository = betsRepository; this.usersRepository = usersRepository; this.dataStitchingService = dataStitchingService; } async getAllBets() { const bets = await this.betsRepository.findAll(); return await this.dataStitchingService.populateBetsWithUsers(bets); } async getBetById(betId) { const bet = await this.betsRepository.findById(betId); const populated = await this.dataStitchingService.populateBetsWithUsers([bet]); return populated[0]; } async getUserBets(userId) { const bets = await this.betsRepository.findByUser(userId); return await this.dataStitchingService.populateBetsWithUsers(bets); } async getGroupBets(groupId) { const bets = await this.betsRepository.findByGroup(groupId); return await this.dataStitchingService.populateBetsWithUsers(bets); } async getPublicBetsExcludingUser(userId) { const bets = await this.betsRepository.findPublicBetsExcludingUser(userId); return await this.dataStitchingService.populateBetsWithUsers(bets); } async createBet(betData) { const { title, description, stake, participants, isPublic, groupId } = betData; if (!title || title.trim() === '') { throw new ValidationError('Bet title is required'); } if (!stake || stake.trim() === '') { throw new ValidationError('Bet stake is required'); } if (!participants || !Array.isArray(participants) || participants.length === 0) { throw new ValidationError('At least one participant is required'); } const normalizedParticipants = participants.map((p) => ({ ...p, user: parseInt(p.user, 10), })); const userIds = normalizedParticipants.map((p) => p.user); for (const userId of userIds) { await this.usersRepository.findById(userId); } const bet = await this.betsRepository.create({ title, description, stake, participants: normalizedParticipants, isPublic: isPublic || false, groupId: groupId || null, }); const populated = await this.dataStitchingService.populateBetsWithUsers([bet]); return populated[0]; } async updateBet(betId, updateData) { if (updateData.title && updateData.title.trim() === '') { throw new ValidationError('Bet title cannot be empty'); } const bet = await this.betsRepository.update(betId, updateData); const populated = await this.dataStitchingService.populateBetsWithUsers([bet]); return populated[0]; } async deleteBet(betId) { return await this.betsRepository.delete(betId); } async declareWinner(betId, winnerId) { await this.usersRepository.findById(winnerId); const bet = await this.betsRepository.update(betId, { winner: winnerId, status: config.BET_STATUS.COMPLETED, endDate: new Date(), }); const populated = await this.dataStitchingService.populateBetsWithUsers([bet]); return populated[0]; } } module.exports = BetsService;