using System.Text.Json; namespace Campaign_Tracker.Server.LegacyData.Schema; public sealed class FileLegacySchemaCheckHistory : ILegacySchemaCheckHistory { private readonly string _filePath; private readonly object _fileLock = new(); private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; public FileLegacySchemaCheckHistory(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentException("History file path is required.", nameof(filePath)); } _filePath = filePath; Directory.CreateDirectory(Path.GetDirectoryName(_filePath) ?? "."); } public void Record(LegacySchemaCheckResult result) { ArgumentNullException.ThrowIfNull(result); var line = JsonSerializer.Serialize(result, JsonOptions) + Environment.NewLine; lock (_fileLock) { File.AppendAllText(_filePath, line); } } public IReadOnlyList GetRecent(int maxCount = 50) { if (maxCount <= 0 || !File.Exists(_filePath)) { return []; } lock (_fileLock) { return File.ReadLines(_filePath) .Where(line => !string.IsNullOrWhiteSpace(line)) .Select(line => JsonSerializer.Deserialize(line, JsonOptions)) .Where(result => result is not null) .Cast() .OrderByDescending(result => result.CheckedAt) .Take(maxCount) .ToArray(); } } }