using Health.Application.AI; namespace Health.Infrastructure.AI; public sealed class EfAiConversationRepository(AppDbContext db) : IAiConversationRepository { private readonly AppDbContext _db = db; public Task GetOwnedAsync(Guid userId, Guid conversationId, CancellationToken ct) => _db.Conversations.FirstOrDefaultAsync(c => c.Id == conversationId && c.UserId == userId, ct); public Task GetAsync(Guid conversationId, CancellationToken ct) => _db.Conversations.FirstOrDefaultAsync(c => c.Id == conversationId, ct); public async Task> ListAsync(Guid userId, CancellationToken ct) => await _db.Conversations .Where(c => c.UserId == userId) .OrderByDescending(c => c.UpdatedAt) .ToListAsync(ct); public async Task> GetMessagesAsync(Guid conversationId, CancellationToken ct) => await _db.ConversationMessages .Where(m => m.ConversationId == conversationId) .OrderBy(m => m.CreatedAt) .ToListAsync(ct); public async Task> GetRecentMessagesAsync(Guid conversationId, int limit, CancellationToken ct) => await _db.ConversationMessages .Where(m => m.ConversationId == conversationId) .OrderByDescending(m => m.CreatedAt) .Take(limit) .ToListAsync(ct); public async Task AddConversationAsync(Conversation conversation, CancellationToken ct) => await _db.Conversations.AddAsync(conversation, ct); public async Task AddMessageAsync(ConversationMessage message, CancellationToken ct) => await _db.ConversationMessages.AddAsync(message, ct); public async Task DeleteLegacyDietCommentaryArtifactsAsync( Guid userId, string promptPrefix, CancellationToken ct) { var candidates = await _db.Conversations .Include(conversation => conversation.Messages) .Where(conversation => conversation.UserId == userId && conversation.Messages.Any(message => message.Role == MessageRole.User && message.Content.StartsWith(promptPrefix))) .ToListAsync(ct); var artifacts = candidates .Where(conversation => DietCommentaryPolicy.IsLegacyArtifact(conversation.Messages)) .ToList(); if (artifacts.Count == 0) return 0; _db.Conversations.RemoveRange(artifacts); await _db.SaveChangesAsync(ct); return artifacts.Count; } public void Delete(Conversation conversation) => _db.Conversations.Remove(conversation); public Task SaveChangesAsync(CancellationToken ct) => _db.SaveChangesAsync(ct); }