using Couchbase.Lite; using WorkTracker.Domain; using WorkTracker.Services.Storage; namespace WorkTracker.Services.Settings; public sealed class CouchbaseLiteAppSettingsService : IAppSettingsService { private const string DefaultSettingsId = "global"; private readonly Collection appSettingsCollection; public CouchbaseLiteAppSettingsService(CouchbaseLiteDatabaseProvider databaseProvider) { appSettingsCollection = databaseProvider.AppSettings; } public Task GetAsync(CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var document = appSettingsCollection.GetDocument(DefaultSettingsId); if (document is not null) { return Task.FromResult(Map(document)); } var defaults = new AppSettingsDocument(); SaveDocument(defaults); return Task.FromResult(defaults); } public async Task SaveAsync(AppSettingsDocument settings, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var existing = await GetAsync(cancellationToken); settings.Id = DefaultSettingsId; settings.CreatedAtUtc = existing.CreatedAtUtc; settings.UpdatedAtUtc = DateTimeOffset.UtcNow; SaveDocument(settings); return settings; } private void SaveDocument(AppSettingsDocument settings) { var document = new MutableDocument(DefaultSettingsId); document.SetString("themeMode", settings.ThemeMode.ToString()); document.SetDouble("standardWorkHoursPerDay", Decimal.ToDouble(settings.StandardWorkHoursPerDay)); document.SetDouble("hourlyGrossRate", Decimal.ToDouble(settings.HourlyGrossRate)); document.SetDouble("profitabilityCoefficient", Decimal.ToDouble(settings.ProfitabilityCoefficient)); document.SetDouble("inpsRate", Decimal.ToDouble(settings.InpsRate)); document.SetDouble("substituteTaxRate", Decimal.ToDouble(settings.SubstituteTaxRate)); document.SetString("currency", settings.Currency); document.SetString("locale", settings.Locale); document.SetString("createdAtUtc", settings.CreatedAtUtc.ToString("O")); document.SetString("updatedAtUtc", settings.UpdatedAtUtc.ToString("O")); appSettingsCollection.Save(document); } private static AppSettingsDocument Map(Document document) { return new AppSettingsDocument { Id = document.Id, ThemeMode = ReadThemeMode(document), StandardWorkHoursPerDay = ReadDecimal(document, "standardWorkHoursPerDay", 8m), HourlyGrossRate = ReadDecimal(document, "hourlyGrossRate", 17.5m), ProfitabilityCoefficient = ReadDecimal(document, "profitabilityCoefficient", 0.67m), InpsRate = ReadDecimal(document, "inpsRate", 0.2607m), SubstituteTaxRate = ReadDecimal(document, "substituteTaxRate", 0.15m), Currency = document.GetString("currency") ?? "EUR", Locale = document.GetString("locale") ?? "it-IT", CreatedAtUtc = ReadDateTimeOffset(document, "createdAtUtc"), UpdatedAtUtc = ReadDateTimeOffset(document, "updatedAtUtc") }; } private static decimal ReadDecimal(Document document, string key, decimal defaultValue) { return document.Contains(key) ? Convert.ToDecimal(document.GetDouble(key)) : defaultValue; } private static AppThemeMode ReadThemeMode(Document document) { var value = document.GetString("themeMode"); return Enum.TryParse(value, ignoreCase: true, out var themeMode) ? themeMode : AppThemeMode.System; } private static DateTimeOffset ReadDateTimeOffset(Document document, string key) { var value = document.GetString(key); return DateTimeOffset.TryParse(value, out var parsed) ? parsed : DateTimeOffset.UtcNow; } }