using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; using Musify.Application.Shared; using Musify.Application.Users.Responses; using X.PagedList.EF; namespace Musify.Application.Users { public record GetUserFollowersQuery(long? ViewerId, long UserId, int PageNumber, int PageSize) : IQuery>>; public class GetUserFollowersQueryHandler(IDatabase database) : IQueryHandler>> { public async ValueTask>> Handle(GetUserFollowersQuery request, CancellationToken cancellationToken) { if (!await database.Users.AnyAsync(u => u.Id == request.UserId, cancellationToken)) return Error.NotFound(); if (!await FollowVisibility.CanViewFollowersAsync(database, request.ViewerId, request.UserId, cancellationToken)) return Error.Forbidden(); var followsQuery = database.UserFollows .AsNoTracking() .Where(f => f.FollowedId == request.UserId); var totalCount = await followsQuery.CountAsync(cancellationToken); var viewerId = request.ViewerId; var page = await followsQuery .OrderByDescending(f => f.CreatedAt) .Select(f => new UserSummaryResponse( f.Follower.Id, f.Follower.Name, f.Follower.FirstName, f.Follower.SecondName, f.Follower.ProfilePictureUrl, viewerId != null && database.UserFollows.Any(v => v.FollowerId == viewerId && v.FollowedId == f.FollowerId))) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); return PaginatedResponse.FromPagedList(page); } } }