using System.Reflection; using Common.Configuration; using Common.Configuration.Arr; using Common.Configuration.ContentBlocker; using Common.Configuration.DownloadCleaner; using Common.Configuration.DownloadClient; using Common.Configuration.General; using Common.Configuration.IgnoredDownloads; using Common.Configuration.Notification; using Common.Configuration.QueueCleaner; using Microsoft.Extensions.Logging; namespace Infrastructure.Configuration; public class ConfigManager : IConfigManager { private readonly ILogger _logger; private readonly IConfigurationProvider _configProvider; private readonly Dictionary _settingsPaths; public ConfigManager( ILogger logger, IConfigurationProvider configProvider) { _logger = logger; _configProvider = configProvider; _settingsPaths = new() { { typeof(GeneralConfig), "general.json" }, { typeof(SonarrConfig), "sonarr.json" }, { typeof(RadarrConfig), "radarr.json" }, { typeof(LidarrConfig), "lidarr.json" }, { typeof(ContentBlockerConfig), "content_blocker.json" }, { typeof(QueueCleanerConfig), "queue_cleaner.json" }, { typeof(DownloadCleanerConfig), "download_cleaner.json" }, { typeof(DownloadClientConfig), "download_client.json" }, { typeof(IgnoredDownloadsConfig), "ignored_downloads.json" }, { typeof(NotificationsConfig), "notifications.json" } }; } public async Task EnsureFilesExist() { foreach ((Type type, string path) in _settingsPaths) { try { object? config; if (_configProvider.FileExists(path)) { config = await ReadConfigurationAsync(type); } else { config = Activator.CreateInstance(type); } if (config is null) { throw new InvalidOperationException($"Failed to create instance of {type}"); } // Create the file with default values or migrate to new model await _configProvider.WriteConfigurationAsync(path, config); } catch (Exception ex) { _logger.LogError(ex, "Failed to ensure configuration file exists: {path}", path); throw; } } } private async Task ReadConfigurationAsync(Type type) { if (type == typeof(GeneralConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(SonarrConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(RadarrConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(LidarrConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(ContentBlockerConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(QueueCleanerConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(DownloadCleanerConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(DownloadClientConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(IgnoredDownloadsConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } if (type == typeof(NotificationsConfig)) { return await _configProvider.ReadConfigurationAsync(_settingsPaths[type]); } throw new NotSupportedException($"Configuration type {type.Name} is not supported."); } public Task GetConfigurationAsync() where T : class, new() { return _configProvider.ReadConfigurationAsync(_settingsPaths[typeof(T)]); } public Task SaveConfigurationAsync(T config) where T : class { string configFileName = _settingsPaths[typeof(T)]; // Validate if it's an IConfig if (config is IConfig configurable) { try { configurable.Validate(); } catch (Exception ex) { _logger.LogError(ex, "Configuration validation failed for {fileName}", configFileName); return Task.FromResult(false); } } return _configProvider.WriteConfigurationAsync(configFileName, config); } public T GetConfiguration() where T : class, new() { return _configProvider.ReadConfiguration(_settingsPaths[typeof(T)]); } public bool SaveConfiguration(T config) where T : class { string configFileName = _settingsPaths[typeof(T)]; // Validate if it's an IConfig if (config is IConfig configurable) { try { configurable.Validate(); } catch (Exception ex) { _logger.LogError(ex, "Configuration validation failed for {fileName}", configFileName); return false; } } try { return _configProvider.WriteConfiguration(configFileName, config); } catch (Exception ex) { _logger.LogError(ex, "Configuration save failed for {fileName}", configFileName); throw; } } }