using Microsoft.EntityFrameworkCore; using WatchIt.Database; using WatchIt.Database.Model.Genres; using WatchIt.Database.Model.Media; using WatchIt.Database.Model.Photos; using WatchIt.DTO.Models.Controllers.Genres.Genre; using WatchIt.DTO.Models.Controllers.Media.Medium; using WatchIt.DTO.Models.Controllers.Media.Medium.Query; using WatchIt.DTO.Query; namespace WatchIt.WebAPI.Repositories.Media; public class MediaRepository : Repository, IMediaRepository { #region CONSTRUCTORS public MediaRepository(DatabaseContext database) : base(database) {} #endregion #region PUBLIC METHODS #region Main public async Task ExistsAsync(long id) => await DefaultSet.AnyAsync(x => x.Id == id); public async Task GetAsync(long id, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.Include(additionalIncludes) .FirstOrDefaultAsync(x => x.Id == id); public async Task GetAsync(long id, Func, IQueryable>? additionalIncludes = null) where T : Medium => await DefaultSet.OfType() .Include(additionalIncludes) .FirstOrDefaultAsync(x => x.Id == id); public async Task> GetAllAsync(MediumFilterQuery filterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.ApplyFilter(filterQuery) .OrderByDescending(x => x.Id) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.Medium) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task> GetAllMoviesAsync(MediumMovieFilterQuery filterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.OfType() .ApplyFilter(filterQuery) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.MediumMovie) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task> GetAllSeriesAsync(MediumSeriesFilterQuery filterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.OfType() .ApplyFilter(filterQuery) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.MediumSeries) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task UpdateAsync(long id, Action updateFunc) where T : Medium { T? entity = await GetAsync(id); if (entity is null) { return false; } updateFunc(entity); DefaultSet.Update(entity); await Database.SaveChangesAsync(); return true; } #endregion #region Genres public async Task> GetMediumGenresAsync(long id, GenreFilterQuery filterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await Database.Set() .Where(x => x.MediumId == id) .Select(x => x.Genre) .ApplyFilter(filterQuery) .ApplyOrder(orderQuery, GenreOrderKeys.Base) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task AddMediumGenreAsync(long mediumId, short genreId) { if (!Database.Set().Any(x => x.MediumId == mediumId && x.GenreId == genreId)) { await AddAsync(new MediumGenre { MediumId = mediumId, GenreId = genreId }); } } public async Task DeleteMediumGenreAsync(long mediumId, short genreId) => await DeleteAsync(new MediumGenre { MediumId = mediumId, GenreId = genreId }); #endregion #region Rating public async Task> GetAllRatedByAccountAsync(long accountId, MediumFilterQuery filterQuery, MediumUserRatedFilterQuery userRatedFilterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.Where(x => x.Ratings .Any(y => y.AccountId == accountId)) .ApplyFilter(filterQuery) .ApplyFilter(userRatedFilterQuery) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.Medium, MediumOrderKeys.MediumUserRated(accountId)) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task> GetAllMoviesRatedByAccountAsync(long accountId, MediumMovieFilterQuery filterQuery, MediumUserRatedFilterQuery userRatedFilterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.OfType() .Where(x => x.Ratings .Any(y => y.AccountId == accountId)) .ApplyFilter(filterQuery) .ApplyFilter(userRatedFilterQuery) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.MediumMovie, MediumOrderKeys.MediumUserRated(accountId)) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task> GetAllSeriesRatedByAccountAsync(long accountId, MediumSeriesFilterQuery filterQuery, MediumUserRatedFilterQuery userRatedFilterQuery, OrderQuery orderQuery, PagingQuery pagingQuery, Func, IQueryable>? additionalIncludes = null) => await DefaultSet.OfType() .Where(x => x.Ratings .Any(y => y.AccountId == accountId)) .ApplyFilter(filterQuery) .ApplyFilter(userRatedFilterQuery) .ApplyOrder(orderQuery, MediumOrderKeys.Base(), MediumOrderKeys.MediumSeries, MediumOrderKeys.MediumUserRated(accountId)) .ApplyPaging(pagingQuery) .Include(additionalIncludes) .ToListAsync(); public async Task GetMediumUserRatingAsync(long mediumId, long accountId, Func, IQueryable>? additionalIncludes = null) => await Database.Set() .Include(additionalIncludes) .FirstOrDefaultAsync(x => x.MediumId == mediumId && x.AccountId == accountId); public async Task UpdateOrAddMediumRatingAsync(long mediumId, long accountId, Func addFunc, Action updateFunc) => await UpdateOrAddAsync(await GetMediumUserRatingAsync(mediumId, accountId), addFunc, updateFunc); public async Task DeleteMediumUserRatingAsync(long mediumId, long accountId) => await DeleteAsync(x => x.MediumId == mediumId && x.AccountId == accountId); #endregion #region View count public async Task UpdateOrAddMediumViewCountAsync(long mediumId, DateOnly date, Func addFunc, Action updateFunc) => await UpdateOrAddAsync(await Database.Set() .FirstOrDefaultAsync(x => x.MediumId == mediumId && x.Date == date), addFunc, updateFunc); #endregion #region Picture public async Task GetMediumPictureAsync(long id, Func, IQueryable>? additionalIncludes = null) => await Database.MediumPictures .Include(additionalIncludes) .FirstOrDefaultAsync(x => x.MediumId == id); public async Task UpdateOrAddMediumPictureAsync(long id, Func addFunc, Action updateFunc) => await UpdateOrAddAsync(await GetMediumPictureAsync(id), addFunc, updateFunc); public async Task DeleteMediumPictureAsync(long id) => await DeleteAsync(new MediumPicture { MediumId = id }); #endregion #endregion }