using Health.Application.AI;

namespace Health.Infrastructure.AI;

public sealed class EfAiConversationRepository(AppDbContext db) : IAiConversationRepository
{
    private readonly AppDbContext _db = db;

    public Task<Conversation?> GetOwnedAsync(Guid userId, Guid conversationId, CancellationToken ct) =>
        _db.Conversations.FirstOrDefaultAsync(c => c.Id == conversationId && c.UserId == userId, ct);

    public Task<Conversation?> GetAsync(Guid conversationId, CancellationToken ct) =>
        _db.Conversations.FirstOrDefaultAsync(c => c.Id == conversationId, ct);

    public async Task<IReadOnlyList<Conversation>> ListAsync(Guid userId, CancellationToken ct) =>
        await _db.Conversations
            .Where(c => c.UserId == userId)
            .OrderByDescending(c => c.UpdatedAt)
            .ToListAsync(ct);

    public async Task<IReadOnlyList<ConversationMessage>> GetMessagesAsync(Guid conversationId, CancellationToken ct) =>
        await _db.ConversationMessages
            .Where(m => m.ConversationId == conversationId)
            .OrderBy(m => m.CreatedAt)
            .ToListAsync(ct);

    public async Task<IReadOnlyList<ConversationMessage>> 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<int> 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);
}
