using System; using System.Collections.Generic; using System.Threading.Tasks; using API.Data; using API.Data.Repositories; using API.DTOs; using API.Entities; using API.Services.Plus; using Hangfire; using Microsoft.Extensions.Logging; namespace API.Services; public interface IRatingService { /// /// Updates the users' rating for a given series /// /// Should include ratings /// /// Task UpdateSeriesRating(AppUser user, UpdateRatingDto updateRatingDto); /// /// Updates the users' rating for a given chapter /// /// Should include ratings /// chapterId must be set /// Task UpdateChapterRating(AppUser user, UpdateRatingDto updateRatingDto); } public class RatingService: IRatingService { private readonly IUnitOfWork _unitOfWork; private readonly IScrobblingService _scrobblingService; private readonly ILogger _logger; public RatingService(IUnitOfWork unitOfWork, IScrobblingService scrobblingService, ILogger logger) { _unitOfWork = unitOfWork; _scrobblingService = scrobblingService; _logger = logger; } public async Task UpdateSeriesRating(AppUser user, UpdateRatingDto updateRatingDto) { var userRating = await _unitOfWork.UserRepository.GetUserRatingAsync(updateRatingDto.SeriesId, user.Id) ?? new AppUserRating(); try { userRating.Rating = Math.Clamp(updateRatingDto.UserRating, 0f, 5f); userRating.HasBeenRated = true; userRating.SeriesId = updateRatingDto.SeriesId; if (userRating.Id == 0) { user.Ratings ??= new List(); user.Ratings.Add(userRating); } _unitOfWork.UserRepository.Update(user); if (!_unitOfWork.HasChanges() || await _unitOfWork.CommitAsync()) { BackgroundJob.Enqueue(() => _scrobblingService.ScrobbleRatingUpdate(user.Id, updateRatingDto.SeriesId, userRating.Rating)); return true; } } catch (Exception ex) { _logger.LogError(ex, "There was an exception saving rating"); } await _unitOfWork.RollbackAsync(); user.Ratings?.Remove(userRating); return false; } public async Task UpdateChapterRating(AppUser user, UpdateRatingDto updateRatingDto) { if (updateRatingDto.ChapterId == null) { return false; } var userRating = await _unitOfWork.UserRepository.GetUserChapterRatingAsync(user.Id, updateRatingDto.ChapterId.Value) ?? new AppUserChapterRating(); try { userRating.Rating = Math.Clamp(updateRatingDto.UserRating, 0f, 5f); userRating.HasBeenRated = true; userRating.SeriesId = updateRatingDto.SeriesId; userRating.ChapterId = updateRatingDto.ChapterId.Value; if (userRating.Id == 0) { user.ChapterRatings ??= new List(); user.ChapterRatings.Add(userRating); } _unitOfWork.UserRepository.Update(user); await _unitOfWork.CommitAsync(); return true; } catch (Exception ex) { _logger.LogError(ex, "There was an exception saving rating"); } await _unitOfWork.RollbackAsync(); user.ChapterRatings?.Remove(userRating); return false; } }