using Journal.Core.Models; namespace Journal.Core.Repositories; public class InMemoryFragmentRepository : IFragmentRepository { private readonly List _store = []; private readonly Lock _lock = new(); public Task> GetAllAsync() { lock (_lock) { return Task.FromResult(_store.ToList()); } } public Task GetByIdAsync(Guid id) { lock (_lock) { return Task.FromResult(_store.FirstOrDefault(f => f.Id == id)); } } public Task AddAsync(Fragment fragment) { if (fragment is null) throw new ArgumentNullException(nameof(fragment)); lock (_lock) { if (fragment.Tags != null) { fragment.Tags = [.. fragment.Tags .Where(t => !string.IsNullOrWhiteSpace(t)) .Select(t => t!.Trim())]; } if (!string.IsNullOrWhiteSpace(fragment.Type)) fragment.Type = fragment.Type.Trim(); if (!string.IsNullOrWhiteSpace(fragment.Description)) fragment.Description = fragment.Description.Trim(); _store.Add(fragment); } return Task.CompletedTask; } public Task RemoveAsync(Guid id) { lock (_lock) { var item = _store.FirstOrDefault(f => f.Id == id); if (item is null) return Task.FromResult(false); return Task.FromResult(_store.Remove(item)); } } public Task UpdateAsync(Guid id, string? type = null, string? description = null, IEnumerable? tags = null, DateTimeOffset? time = null) { lock (_lock) { var item = _store.FirstOrDefault(f => f.Id == id); if (item is null) return Task.FromResult(false); if (type != null) { if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Type cannot be empty", nameof(type)); item.Type = type.Trim(); } if (description != null) { if (string.IsNullOrWhiteSpace(description)) throw new ArgumentException("Description cannot be empty", nameof(description)); item.Description = description.Trim(); } if (tags != null) { item.Tags = [.. tags .Where(t => !string.IsNullOrWhiteSpace(t)) .Select(t => t!.Trim())]; } if (time.HasValue) item.Time = time.Value; return Task.FromResult(true); } } public Task> GetByTagAsync(string tag) { var q = tag?.Trim(); if (string.IsNullOrWhiteSpace(q)) return Task.FromResult(new List()); lock (_lock) { return Task.FromResult(_store.Where(f => f.Tags?.Any(t => !string.IsNullOrWhiteSpace(t) && t.Contains(q, StringComparison.OrdinalIgnoreCase)) == true).ToList()); } } public Task> GetByTypeAsync(string type) { var q = type?.Trim(); if (string.IsNullOrWhiteSpace(q)) return Task.FromResult(new List()); lock (_lock) { return Task.FromResult(_store.Where(f => !string.IsNullOrWhiteSpace(f.Type) && f.Type.Trim().Contains(q, StringComparison.OrdinalIgnoreCase)).ToList()); } } public Task> SearchAsync(string? type = null, string? tag = null, DateTimeOffset? timeAfter = null) { var results = _store.AsEnumerable(); var qType = type?.Trim(); var qTag = tag?.Trim(); lock (_lock) { if (!string.IsNullOrWhiteSpace(qType)) results = results.Where(f => !string.IsNullOrWhiteSpace(f.Type) && f.Type.Trim().Contains(qType, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(qTag)) results = results.Where(f => f.Tags?.Any(t => !string.IsNullOrWhiteSpace(t) && t.Contains(qTag, StringComparison.OrdinalIgnoreCase)) == true); if (timeAfter.HasValue) results = results.Where(f => f.Time > timeAfter.Value); return Task.FromResult(results.ToList()); } } }