using System; using System.Collections.Generic; using System.Linq; using MongoDB.Bson; namespace StellaOps.Concelier.Connector.CertIn.Internal; internal sealed record CertInCursor( DateTimeOffset? LastPublished, IReadOnlyCollection PendingDocuments, IReadOnlyCollection PendingMappings) { public static CertInCursor Empty { get; } = new(null, Array.Empty(), Array.Empty()); public BsonDocument ToBsonDocument() { var document = new BsonDocument { ["pendingDocuments"] = new BsonArray(PendingDocuments.Select(id => id.ToString())), ["pendingMappings"] = new BsonArray(PendingMappings.Select(id => id.ToString())), }; if (LastPublished.HasValue) { document["lastPublished"] = LastPublished.Value.UtcDateTime; } return document; } public static CertInCursor FromBson(BsonDocument? document) { if (document is null || document.ElementCount == 0) { return Empty; } var lastPublished = document.TryGetValue("lastPublished", out var dateValue) ? ParseDate(dateValue) : null; return new CertInCursor( lastPublished, ReadGuidArray(document, "pendingDocuments"), ReadGuidArray(document, "pendingMappings")); } public CertInCursor WithLastPublished(DateTimeOffset? timestamp) => this with { LastPublished = timestamp }; public CertInCursor WithPendingDocuments(IEnumerable ids) => this with { PendingDocuments = ids?.Distinct().ToArray() ?? Array.Empty() }; public CertInCursor WithPendingMappings(IEnumerable ids) => this with { PendingMappings = ids?.Distinct().ToArray() ?? Array.Empty() }; private static DateTimeOffset? ParseDate(BsonValue value) => value.BsonType switch { BsonType.DateTime => DateTime.SpecifyKind(value.ToUniversalTime(), DateTimeKind.Utc), BsonType.String when DateTimeOffset.TryParse(value.AsString, out var parsed) => parsed.ToUniversalTime(), _ => null, }; private static IReadOnlyCollection ReadGuidArray(BsonDocument document, string field) { if (!document.TryGetValue(field, out var value) || value is not BsonArray array) { return Array.Empty(); } var results = new List(array.Count); foreach (var element in array) { if (element is null) { continue; } if (Guid.TryParse(element.ToString(), out var guid)) { results.Add(guid); } } return results; } }