using LightlessSyncServer.Services.Interfaces; using LightlessSyncShared.Data; using LightlessSyncShared.Models; using Microsoft.EntityFrameworkCore; namespace LightlessSyncServer.Services { public class PruneService(LightlessDbContext dbContext) : IPruneService { private readonly LightlessDbContext _dbContext = dbContext; public async Task CountPrunableUsersAsync(string groupGid, int days, CancellationToken ct) { var allGroupUsers = await _dbContext.GroupPairs .Include(p => p.GroupUser) .Include(p => p.Group) .Where(g => g.GroupGID == groupGid) .ToListAsync(ct).ConfigureAwait(false); var inactivitySpan = GetInactivitySpan(days); var now = DateTime.UtcNow; var usersToPrune = allGroupUsers.Where(p => !p.IsPinned && !p.IsModerator && !string.Equals(p.Group.OwnerUID, p.GroupUserUID, StringComparison.Ordinal) && p.GroupUser.LastLoggedIn < now - inactivitySpan); return usersToPrune.Count(); } public async Task> ExecutePruneAsync(string groupGid, int days, CancellationToken ct) { var allGroupUsers = await _dbContext.GroupPairs .Include(p => p.GroupUser) .Include(p => p.Group) .Where(g => g.GroupGID == groupGid) .ToListAsync(ct).ConfigureAwait(false); var inactivitySpan = GetInactivitySpan(days); var now = DateTime.UtcNow; var usersToPrune = allGroupUsers.Where(p => !p.IsPinned && !p.IsModerator && !string.Equals(p.Group.OwnerUID, p.GroupUserUID, StringComparison.Ordinal) && p.GroupUser.LastLoggedIn < now - inactivitySpan) .ToList(); _dbContext.GroupPairs.RemoveRange(usersToPrune); await _dbContext.SaveChangesAsync(ct).ConfigureAwait(false); return usersToPrune; } private static TimeSpan GetInactivitySpan(int days) => days == 0 ? TimeSpan.FromMinutes(15) : TimeSpan.FromDays(days); } }