using Microsoft.EntityFrameworkCore; using SimpleToolkit.Extensions; using WatchIt.Common.Model.Genres; using WatchIt.Common.Model.Media; using WatchIt.Common.Model.Photos; using WatchIt.Common.Model.Rating; using WatchIt.Database; using WatchIt.Database.Model.Media; using WatchIt.Database.Model.Rating; using WatchIt.Database.Model.ViewCount; using WatchIt.WebAPI.Services.Controllers.Common; using WatchIt.WebAPI.Services.Utility.User; namespace WatchIt.WebAPI.Services.Controllers.Media; public class MediaControllerService(DatabaseContext database, IUserService userService) : IMediaControllerService { #region PUBLIC METHODS #region Main public async Task GetMedia(long mediaId) { Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } MediaMovie? movie = await database.MediaMovies.FirstOrDefaultAsync(x => x.Id == mediaId); MediaResponse mediaResponse = new MediaResponse(item, movie is not null ? MediaType.Movie : MediaType.Series); return RequestResult.Ok(mediaResponse); } #endregion #region Genres public async Task GetMediaGenres(long mediaId) { Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } IEnumerable genres = item.MediaGenres.Select(x => new GenreResponse(x.Genre)); return RequestResult.Ok(genres); } public async Task PostMediaGenre(long mediaId, short genreId) { UserValidator validator = userService.GetValidator().MustBeAdmin(); if (!validator.IsValid) { return RequestResult.Forbidden(); } Database.Model.Media.Media? mediaItem = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); Database.Model.Common.Genre? genreItem = await database.Genres.FirstOrDefaultAsync(x => x.Id == genreId); if (mediaItem is null || genreItem is null) { return RequestResult.NotFound(); } await database.MediaGenres.AddAsync(new MediaGenre { GenreId = genreId, MediaId = mediaId, }); await database.SaveChangesAsync(); return RequestResult.Ok(); } public async Task DeleteMediaGenre(long mediaId, short genreId) { UserValidator validator = userService.GetValidator().MustBeAdmin(); if (!validator.IsValid) { return RequestResult.Forbidden(); } MediaGenre? item = await database.MediaGenres.FirstOrDefaultAsync(x => x.MediaId == mediaId && x.GenreId == genreId); if (item is null) { return RequestResult.NotFound(); } database.MediaGenres.Attach(item); database.MediaGenres.Remove(item); await database.SaveChangesAsync(); return RequestResult.Ok(); } #endregion #region Rating public async Task GetMediaRating(long mediaId) { Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } RatingResponse ratingResponse = RatingResponse.Create(item.RatingMedia); return RequestResult.Ok(ratingResponse); } public async Task GetMediaRatingByUser(long mediaId, long userId) { Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } short? rating = item.RatingMedia.FirstOrDefault(x => x.AccountId == userId)?.Rating; if (!rating.HasValue) { return RequestResult.NotFound(); } return RequestResult.Ok(rating.Value); } public async Task PutMediaRating(long mediaId, RatingRequest data) { short ratingValue = data.Rating; if (ratingValue < 1 || ratingValue > 10) { return RequestResult.BadRequest(); } Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } long userId = userService.GetUserId(); RatingMedia? rating = item.RatingMedia.FirstOrDefault(x => x.AccountId == userId); if (rating is not null) { rating.Rating = ratingValue; } else { rating = new RatingMedia { AccountId = userId, MediaId = mediaId, Rating = ratingValue }; await database.RatingsMedia.AddAsync(rating); } await database.SaveChangesAsync(); return RequestResult.Ok(); } public async Task DeleteMediaRating(long mediaId) { long userId = userService.GetUserId(); RatingMedia? item = await database.RatingsMedia.FirstOrDefaultAsync(x => x.MediaId == mediaId && x.AccountId == userId); if (item is null) { return RequestResult.Ok(); } database.RatingsMedia.Attach(item); database.RatingsMedia.Remove(item); await database.SaveChangesAsync(); return RequestResult.Ok(); } #endregion #region View count public async Task PostMediaView(long mediaId) { Database.Model.Media.Media? item = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (item is null) { return RequestResult.NotFound(); } DateOnly dateNow = DateOnly.FromDateTime(DateTime.Now); ViewCountMedia? viewCount = await database.ViewCountsMedia.FirstOrDefaultAsync(x => x.MediaId == mediaId && x.Date == dateNow); if (viewCount is null) { viewCount = new ViewCountMedia { MediaId = mediaId, Date = dateNow, ViewCount = 1 }; await database.ViewCountsMedia.AddAsync(viewCount); } else { viewCount.ViewCount++; } await database.SaveChangesAsync(); return RequestResult.Ok(); } #endregion #region Poster public async Task GetMediaPoster(long mediaId) { Database.Model.Media.Media? media = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (media is null) { return RequestResult.BadRequest(); } MediaPosterImage? poster = media.MediaPosterImage; if (poster is null) { return RequestResult.NotFound(); } MediaPosterResponse data = new MediaPosterResponse(poster); return RequestResult.Ok(data); } public async Task PutMediaPoster(long mediaId, MediaPosterRequest data) { UserValidator validator = userService.GetValidator().MustBeAdmin(); if (!validator.IsValid) { return RequestResult.Forbidden(); } Database.Model.Media.Media? media = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (media is null) { return RequestResult.BadRequest(); } if (media.MediaPosterImage is null) { MediaPosterImage image = data.CreateMediaPosterImage(); await database.MediaPosterImages.AddAsync(image); await database.SaveChangesAsync(); media.MediaPosterImageId = image.Id; } else { data.UpdateMediaPosterImage(media.MediaPosterImage); } await database.SaveChangesAsync(); MediaPosterResponse returnData = new MediaPosterResponse(media.MediaPosterImage); return RequestResult.Ok(returnData); } public async Task DeleteMediaPoster(long mediaId) { UserValidator validator = userService.GetValidator().MustBeAdmin(); if (!validator.IsValid) { return RequestResult.Forbidden(); } Database.Model.Media.Media? media = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (media?.MediaPosterImage != null) { database.MediaPosterImages.Attach(media.MediaPosterImage); database.MediaPosterImages.Remove(media.MediaPosterImage); await database.SaveChangesAsync(); } return RequestResult.NoContent(); } #endregion #region Photos public async Task GetMediaPhotos(long mediaId, PhotoQueryParameters queryParameters) { Database.Model.Media.Media? media = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (media is null) { return RequestResult.NotFound(); } IEnumerable imagesRaw = await database.MediaPhotoImages.Where(x => x.MediaId == mediaId).ToListAsync(); IEnumerable images = imagesRaw.Select(x => new PhotoResponse(x)); images = queryParameters.PrepareData(images); return RequestResult.Ok(images); } public Task GetMediaPhotoRandomBackground(long mediaId) { MediaPhotoImage? image = database.MediaPhotoImages.Where(x => x.MediaId == mediaId && x.MediaPhotoImageBackground != null).Random(); if (image is null) { return Task.FromResult(RequestResult.NotFound()); } PhotoResponse data = new PhotoResponse(image); return Task.FromResult(RequestResult.Ok(data)); } public async Task PostMediaPhoto(long mediaId, MediaPhotoRequest data) { UserValidator validator = userService.GetValidator().MustBeAdmin(); if (!validator.IsValid) { return RequestResult.Forbidden(); } Database.Model.Media.Media? media = await database.Media.FirstOrDefaultAsync(x => x.Id == mediaId); if (media is null) { return RequestResult.NotFound(); } MediaPhotoImage item = data.CreateMediaPhotoImage(mediaId); await database.MediaPhotoImages.AddAsync(item); await database.SaveChangesAsync(); MediaPhotoImageBackground? background = data.CreateMediaPhotoImageBackground(item.Id); if (background is not null) { await database.MediaPhotoImageBackgrounds.AddAsync(background); await database.SaveChangesAsync(); } return RequestResult.Created($"photos/{item.Id}", new PhotoResponse(item)); } #endregion #endregion }