using AutoMapper; using MongoDB.Bson; using ShoppingAssistantApi.Application.Exceptions; using ShoppingAssistantApi.Application.GlobalInstances; using ShoppingAssistantApi.Application.IRepositories; using ShoppingAssistantApi.Application.IServices; using ShoppingAssistantApi.Application.Models.CreateDtos; using ShoppingAssistantApi.Application.Models.Dtos; using ShoppingAssistantApi.Application.Paging; using ShoppingAssistantApi.Domain.Entities; using ShoppingAssistantApi.Domain.Enums; namespace ShoppingAssistantApi.Infrastructure.Services; public class WishlistsService : IWishlistsService { private readonly IWishlistsRepository _wishlistsRepository; private readonly IMessagesRepository _messagesRepository; private readonly IProductsRepository _productsRepository; private readonly IMapper _mapper; public WishlistsService(IWishlistsRepository wishlistRepository, IMessagesRepository messageRepository, IProductsRepository productRepository, IMapper mapper) { _wishlistsRepository = wishlistRepository; _messagesRepository = messageRepository; _productsRepository = productRepository; _mapper = mapper; } public async Task StartPersonalWishlistAsync(WishlistCreateDto dto, CancellationToken cancellationToken) { var newWishlist = _mapper.Map(dto); if (!Enum.TryParse(newWishlist.Type, true, out var enumValue) || !Enum.GetValues().Contains(enumValue)) { throw new InvalidDataException("Provided type is invalid."); } newWishlist.CreatedById = (ObjectId) GlobalUser.Id; newWishlist.CreatedDateUtc = DateTime.UtcNow; newWishlist.Name = $"{newWishlist.Type} Search"; var createdWishlist = await _wishlistsRepository.AddAsync(newWishlist, cancellationToken); var newMessage = new Message { Text = dto.FirstMessageText, Role = MessageRoles.User.ToString(), CreatedById = (ObjectId) GlobalUser.Id, CreatedDateUtc = DateTime.UtcNow, WishlistId = createdWishlist.Id }; var createdMessage = await _messagesRepository.AddAsync(newMessage, cancellationToken); return _mapper.Map(createdWishlist); } public async Task AddMessageToPersonalWishlistAsync(string wishlistId, MessageCreateDto dto, CancellationToken cancellationToken) { var newMessage = _mapper.Map(dto); if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } newMessage.Role = MessageRoles.User.ToString(); newMessage.CreatedById = (ObjectId) GlobalUser.Id; newMessage.CreatedDateUtc = DateTime.UtcNow; newMessage.WishlistId = wishlistObjectId; await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); var createdMessage = await _messagesRepository.AddAsync(newMessage, cancellationToken); return _mapper.Map(createdMessage); } public async Task> GetPersonalWishlistsPageAsync(int pageNumber, int pageSize, CancellationToken cancellationToken) { var entities = await _wishlistsRepository.GetPageAsync(pageNumber, pageSize, x => x.CreatedById == GlobalUser.Id, cancellationToken); var dtos = _mapper.Map>(entities); var count = await _wishlistsRepository.GetTotalCountAsync(); return new PagedList(dtos, pageNumber, pageSize, count); } public async Task GetPersonalWishlistAsync(string wishlistId, CancellationToken cancellationToken) { if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } var entity = await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); return _mapper.Map(entity); } public async Task> GetMessagesPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken) { if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); var entities = await _messagesRepository.GetPageStartingFromEndAsync(pageNumber, pageSize, x => x.WishlistId == wishlistObjectId, cancellationToken); var dtos = _mapper.Map>(entities); var count = await _messagesRepository.GetCountAsync(x => x.WishlistId == wishlistObjectId, cancellationToken); return new PagedList(dtos, pageNumber, pageSize, count); } public async Task AddProductToPersonalWishlistAsync(string wishlistId, ProductCreateDto dto, CancellationToken cancellationToken) { var newProduct = _mapper.Map(dto); if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); newProduct.CreatedById = (ObjectId) GlobalUser.Id; newProduct.CreatedDateUtc = DateTime.UtcNow; newProduct.WishlistId = wishlistObjectId; var createdProduct = await _productsRepository.AddAsync(newProduct, cancellationToken); return _mapper.Map(createdProduct); } public async Task> GetProductsPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken) { if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); var entities = await _productsRepository.GetPageAsync(pageNumber, pageSize, x => x.WishlistId == wishlistObjectId, cancellationToken); var dtos = _mapper.Map>(entities); var count = await _productsRepository.GetCountAsync(x => x.WishlistId == wishlistObjectId, cancellationToken); return new PagedList(dtos, pageNumber, pageSize, count); } public async Task DeletePersonalWishlistAsync(string wishlistId, CancellationToken cancellationToken) { if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) { throw new InvalidDataException("Provided id is invalid."); } var entity = await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); entity.LastModifiedById = GlobalUser.Id; entity.LastModifiedDateUtc = DateTime.UtcNow; await _wishlistsRepository.DeleteAsync(entity, cancellationToken); return _mapper.Map(entity); } private async Task TryGetPersonalWishlist(ObjectId wishlistId, CancellationToken cancellationToken) { var entity = await _wishlistsRepository.GetWishlistAsync(x => x.Id == wishlistId, cancellationToken); if (entity.CreatedById != GlobalUser.Id) { throw new UnAuthorizedException(); } if (entity == null) { throw new EntityNotFoundException(); } return entity; } }