using System.Text.Json; using System.Text.Json.Nodes; using WebApp.Models; namespace WebApp.Services; /// /// Persists chapter settings to Data/appsettings.json. /// public class ChapterSettingsWriter : IChapterSettingsWriter { private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true }; private readonly IWebHostEnvironment _environment; private readonly IConfiguration _configuration; private readonly ILogger _logger; public ChapterSettingsWriter( IWebHostEnvironment environment, IConfiguration configuration, ILogger logger) { _environment = environment; _configuration = configuration; _logger = logger; } public async Task WriteAsync(ChapterSettings settings, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(settings); var appSettingsPath = GetAppSettingsPath(); var dataDir = Path.GetDirectoryName(appSettingsPath); if (dataDir != null && !Directory.Exists(dataDir)) Directory.CreateDirectory(dataDir); JsonObject root; if (File.Exists(appSettingsPath)) { var existingJson = await File.ReadAllTextAsync(appSettingsPath, cancellationToken); root = JsonNode.Parse(existingJson) as JsonObject ?? []; } else { root = []; } var incoming = JsonSerializer.SerializeToNode(settings, JsonOptions) as JsonObject ?? []; if (root["ChapterSettings"] is JsonObject existing) { foreach (var property in incoming) existing[property.Key] = property.Value?.DeepClone(); } else { root["ChapterSettings"] = incoming; } await File.WriteAllTextAsync(appSettingsPath, root.ToJsonString(JsonOptions), cancellationToken); if (_configuration is IConfigurationRoot configurationRoot) configurationRoot.Reload(); _logger.LogInformation("Chapter settings written to {Path}", appSettingsPath); } public async Task UpdateCompetitionYearAsync(string competitionYear, CancellationToken cancellationToken = default) { var settings = ChapterSettings.FromConfiguration(_configuration); settings.CompetitionYear = competitionYear; await WriteAsync(settings, cancellationToken); } private string GetAppSettingsPath() => Path.Combine(_environment.ContentRootPath, "Data", "appsettings.json"); }