using System.ComponentModel.DataAnnotations; using Journal.Core.Dtos; using Journal.Core.Models; using Journal.Core.Repositories; namespace Journal.Core.Services.Todos; public class TodoService(ITodoRepository repo) : ITodoService { private readonly ITodoRepository _repo = repo ?? throw new ArgumentNullException(nameof(repo)); private static TodoItemDto MapItem(TodoItem i) => new( i.Id, i.ListId, i.Text, i.Done, i.SortOrder ); private TodoListDto MapList(TodoList l) { var items = _repo.GetItemsByListId(l.Id); return new TodoListDto( l.Id, l.Label, l.CreatedAt, [.. items.Select(MapItem)] ); } public List GetAllLists() { var lists = _repo.GetAllLists(); return [.. lists.Select(MapList)]; } public TodoListDto? GetListById(Guid id) { var l = _repo.GetListById(id); return l is null ? null : MapList(l); } public TodoListDto CreateList(CreateTodoListDto dto) { ArgumentNullException.ThrowIfNull(dto); var ctx = new ValidationContext(dto); Validator.ValidateObject(dto, ctx, validateAllProperties: true); var list = new TodoList(dto.Label); _repo.AddList(list); return new TodoListDto(list.Id, list.Label, list.CreatedAt, []); } public bool UpdateList(Guid id, UpdateTodoListDto dto) { ArgumentNullException.ThrowIfNull(dto); if (dto.Label is not null && string.IsNullOrWhiteSpace(dto.Label)) throw new ValidationException("Label cannot be empty"); return _repo.UpdateList(id, dto.Label?.Trim()); } public bool RemoveList(Guid id) => _repo.RemoveList(id); public TodoItemDto CreateItem(CreateTodoItemDto dto) { ArgumentNullException.ThrowIfNull(dto); var ctx = new ValidationContext(dto); Validator.ValidateObject(dto, ctx, validateAllProperties: true); if (dto.ListId == Guid.Empty) throw new ValidationException("ListId is required"); var item = new TodoItem(dto.ListId, dto.Text, dto.SortOrder ?? 0); _repo.AddItem(item); return MapItem(item); } public bool UpdateItem(Guid id, UpdateTodoItemDto dto) { ArgumentNullException.ThrowIfNull(dto); if (dto.Text is not null && string.IsNullOrWhiteSpace(dto.Text)) throw new ValidationException("Text cannot be empty"); return _repo.UpdateItem(id, dto.Text?.Trim(), dto.Done, dto.SortOrder); } public bool RemoveItem(Guid id) => _repo.RemoveItem(id); }