using Health.Application.Users; namespace Health.Infrastructure.Users; public sealed class EfUserRepository(AppDbContext db) : IUserRepository { private readonly AppDbContext _db = db; public Task GetAsync(Guid userId, CancellationToken ct) => _db.Users.FirstOrDefaultAsync(u => u.Id == userId, ct); public async Task GetAccountFileReferencesAsync(Guid userId, CancellationToken ct) { var fileUrls = new List(); var userAvatar = await _db.Users .Where(u => u.Id == userId) .Select(u => u.AvatarUrl) .FirstOrDefaultAsync(ct); AddIfPresent(fileUrls, userAvatar); var doctorProfile = await _db.DoctorProfiles .Where(p => p.UserId == userId) .Select(p => new { p.DoctorId, p.AvatarUrl }) .FirstOrDefaultAsync(ct); AddIfPresent(fileUrls, doctorProfile?.AvatarUrl); if (doctorProfile?.DoctorId != null) { var doctorAvatar = await _db.Doctors .Where(d => d.Id == doctorProfile.DoctorId) .Select(d => d.AvatarUrl) .FirstOrDefaultAsync(ct); AddIfPresent(fileUrls, doctorAvatar); } fileUrls.AddRange(await _db.Reports .Where(r => r.UserId == userId && r.FileUrl != "") .Select(r => r.FileUrl) .ToListAsync(ct)); var metadata = await _db.ConversationMessages .Where(m => m.Conversation!.UserId == userId && m.MetadataJson != null && m.MetadataJson != "") .Select(m => m.MetadataJson!) .ToListAsync(ct); return new AccountFileReferences(fileUrls.Distinct().ToList(), metadata); } public Task SaveChangesAsync(CancellationToken ct) => _db.SaveChangesAsync(ct); public async Task DeleteAccountDataAsync(Guid userId, CancellationToken ct) { await using var transaction = await _db.Database.BeginTransactionAsync(ct); var profile = await _db.DoctorProfiles.FirstOrDefaultAsync(p => p.UserId == userId, ct); if (profile?.DoctorId != null) { await _db.Users.Where(u => u.DoctorId == profile.DoctorId) .ExecuteUpdateAsync(u => u.SetProperty(x => x.DoctorId, (Guid?)null), ct); await _db.Doctors.Where(d => d.Id == profile.DoctorId).ExecuteDeleteAsync(ct); } await _db.HealthRecords.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct); await _db.MedicationLogs.Where(l => l.UserId == userId).ExecuteDeleteAsync(ct); await _db.Medications.Where(m => m.UserId == userId).ExecuteDeleteAsync(ct); await _db.DietFoodItems.Where(i => i.DietRecord!.UserId == userId).ExecuteDeleteAsync(ct); await _db.DietRecords.Where(d => d.UserId == userId).ExecuteDeleteAsync(ct); await _db.ExercisePlanItems.Where(i => i.Plan!.UserId == userId).ExecuteDeleteAsync(ct); await _db.ExercisePlans.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await _db.ReportAnalysisTasks.Where(t => _db.Reports.Any(r => r.Id == t.ReportId && r.UserId == userId)).ExecuteDeleteAsync(ct); await _db.Reports.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct); await _db.ConversationMessages.Where(m => m.Conversation!.UserId == userId).ExecuteDeleteAsync(ct); await _db.Conversations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct); await _db.ConsultationMessages.Where(m => m.Consultation!.UserId == userId).ExecuteDeleteAsync(ct); await _db.Consultations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct); await _db.FollowUps.Where(f => f.UserId == userId).ExecuteDeleteAsync(ct); await _db.RefreshTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct); await _db.DeviceTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct); await _db.UserNotifications.Where(n => n.UserId == userId).ExecuteDeleteAsync(ct); await _db.NotificationOutbox.Where(n => n.UserId == userId).ExecuteDeleteAsync(ct); await _db.NotificationPreferences.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await _db.HealthArchives.Where(a => a.UserId == userId).ExecuteDeleteAsync(ct); await _db.AiWriteCommands.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct); await _db.DoctorProfiles.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct); await _db.Users.Where(u => u.Id == userId).ExecuteDeleteAsync(ct); await transaction.CommitAsync(ct); } private static void AddIfPresent(List values, string? value) { if (!string.IsNullOrWhiteSpace(value)) values.Add(value); } }