using System.ComponentModel.DataAnnotations; using Journal.Core.Dtos; using Journal.Core.Models; using Journal.Core.Repositories; namespace Journal.Core.Services.Conversations; public class ConversationService(IConversationRepository repo) : IConversationService { private readonly IConversationRepository _repo = repo ?? throw new ArgumentNullException(nameof(repo)); private static ConversationDto MapSummary(Conversation c) => new(c.Id, c.Title, c.CreatedAt, c.UpdatedAt); private static ConversationMessageDto MapMessage(ConversationMessage m) => new(m.Id, m.Role, m.Text, m.CreatedAt); public List GetAll() { var items = _repo.GetAll(); return [.. items.Select(MapSummary)]; } public ConversationDetailDto? GetById(Guid id) { var c = _repo.GetById(id); if (c is null) return null; var messages = _repo.GetMessages(id); return new ConversationDetailDto( c.Id, c.Title, [.. messages.Select(MapMessage)], c.CreatedAt, c.UpdatedAt); } public ConversationDto Create(CreateConversationDto dto) { ArgumentNullException.ThrowIfNull(dto); var ctx = new ValidationContext(dto); Validator.ValidateObject(dto, ctx, validateAllProperties: true); var conversation = new Conversation(dto.Title); _repo.Add(conversation); return MapSummary(conversation); } public bool Update(Guid id, UpdateConversationDto dto) { ArgumentNullException.ThrowIfNull(dto); if (dto.Title is not null && string.IsNullOrWhiteSpace(dto.Title)) throw new ValidationException("Title cannot be empty"); return _repo.Update(id, dto.Title?.Trim()); } public bool Remove(Guid id) => _repo.Remove(id); public ConversationMessageDto AddMessage(Guid conversationId, string role, string text) { var message = new ConversationMessage(conversationId, role, text); _repo.AddMessage(message); return MapMessage(message); } public List GetMessages(Guid conversationId) { var messages = _repo.GetMessages(conversationId); return [.. messages.Select(MapMessage)]; } }