using Common.Configuration; using Common.Configuration.Arr; using Common.Configuration.ContentBlocker; using Common.Configuration.DownloadCleaner; using Common.Configuration.DownloadClient; using Common.Configuration.IgnoredDownloads; using Common.Configuration.QueueCleaner; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Infrastructure.Configuration; /// /// Provides configuration management for various components with thread-safe file access. /// public interface IConfigurationManager { // Configuration files Task GetConfigurationAsync(string configFileName) where T : class, new(); Task SaveConfigurationAsync(string configFileName, T config) where T : class; Task UpdateConfigurationPropertyAsync(string configFileName, string propertyPath, T value); Task MergeConfigurationAsync(string configFileName, T newValues) where T : class; Task DeleteConfigurationAsync(string configFileName); IEnumerable ListConfigurationFiles(); // Specific configuration types (for common configs) Task GetSonarrConfigAsync(); Task GetRadarrConfigAsync(); Task GetLidarrConfigAsync(); Task GetContentBlockerConfigAsync(); Task GetQueueCleanerConfigAsync(); Task GetDownloadCleanerConfigAsync(); Task GetDownloadClientConfigAsync(); Task GetIgnoredDownloadsConfigAsync(); Task SaveSonarrConfigAsync(SonarrConfig config); Task SaveRadarrConfigAsync(RadarrConfig config); Task SaveLidarrConfigAsync(LidarrConfig config); Task SaveContentBlockerConfigAsync(ContentBlockerConfig config); Task SaveQueueCleanerConfigAsync(QueueCleanerConfig config); Task SaveDownloadCleanerConfigAsync(DownloadCleanerConfig config); Task SaveDownloadClientConfigAsync(DownloadClientConfig config); Task SaveIgnoredDownloadsConfigAsync(IgnoredDownloadsConfig config); } public class ConfigurationManager : IConfigurationManager { private readonly ILogger _logger; private readonly JsonConfigurationProvider _configProvider; private readonly IOptionsMonitor _sonarrConfig; private readonly IOptionsMonitor _radarrConfig; private readonly IOptionsMonitor _lidarrConfig; private readonly IOptionsMonitor _contentBlockerConfig; private readonly IOptionsMonitor _queueCleanerConfig; private readonly IOptionsMonitor _downloadCleanerConfig; private readonly IOptionsMonitor _downloadClientConfig; private readonly IOptionsMonitor _ignoredDownloadsConfig; // Define standard config file names private const string SonarrConfigFile = "sonarr.json"; private const string RadarrConfigFile = "radarr.json"; private const string LidarrConfigFile = "lidarr.json"; private const string ContentBlockerConfigFile = "contentblocker.json"; private const string QueueCleanerConfigFile = "queuecleaner.json"; private const string DownloadCleanerConfigFile = "downloadcleaner.json"; private const string DownloadClientConfigFile = "downloadclient.json"; private const string IgnoredDownloadsConfigFile = "ignoreddownloads.json"; public ConfigurationManager( ILogger logger, JsonConfigurationProvider configProvider, IOptionsMonitor sonarrConfig, IOptionsMonitor radarrConfig, IOptionsMonitor lidarrConfig, IOptionsMonitor contentBlockerConfig, IOptionsMonitor queueCleanerConfig, IOptionsMonitor downloadCleanerConfig, IOptionsMonitor downloadClientConfig, IOptionsMonitor ignoredDownloadsConfig) { _logger = logger; _configProvider = configProvider; _sonarrConfig = sonarrConfig; _radarrConfig = radarrConfig; _lidarrConfig = lidarrConfig; _contentBlockerConfig = contentBlockerConfig; _queueCleanerConfig = queueCleanerConfig; _downloadCleanerConfig = downloadCleanerConfig; _downloadClientConfig = downloadClientConfig; _ignoredDownloadsConfig = ignoredDownloadsConfig; } // Generic configuration methods public Task GetConfigurationAsync(string configFileName) where T : class, new() { return _configProvider.ReadConfigurationAsync(configFileName); } public Task SaveConfigurationAsync(string configFileName, T config) where T : class { // 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 Task UpdateConfigurationPropertyAsync(string configFileName, string propertyPath, T value) { return _configProvider.UpdateConfigurationPropertyAsync(configFileName, propertyPath, value); } public Task MergeConfigurationAsync(string configFileName, T newValues) where T : class { return _configProvider.MergeConfigurationAsync(configFileName, newValues); } public Task DeleteConfigurationAsync(string configFileName) { return _configProvider.DeleteConfigurationAsync(configFileName); } public IEnumerable ListConfigurationFiles() { return _configProvider.ListConfigurationFiles(); } // Specific configuration type methods public async Task GetSonarrConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(SonarrConfigFile); return config ?? _sonarrConfig.CurrentValue; } public async Task GetRadarrConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(RadarrConfigFile); return config ?? _radarrConfig.CurrentValue; } public async Task GetLidarrConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(LidarrConfigFile); return config ?? _lidarrConfig.CurrentValue; } public async Task GetContentBlockerConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(ContentBlockerConfigFile); return config ?? _contentBlockerConfig.CurrentValue; } public async Task GetQueueCleanerConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(QueueCleanerConfigFile); return config ?? _queueCleanerConfig.CurrentValue; } public async Task GetDownloadCleanerConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(DownloadCleanerConfigFile); return config ?? _downloadCleanerConfig.CurrentValue; } public async Task GetDownloadClientConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(DownloadClientConfigFile); return config ?? _downloadClientConfig.CurrentValue; } public Task SaveSonarrConfigAsync(SonarrConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(SonarrConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "Sonarr configuration validation failed"); return Task.FromResult(false); } } public Task SaveRadarrConfigAsync(RadarrConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(RadarrConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "Radarr configuration validation failed"); return Task.FromResult(false); } } public Task SaveLidarrConfigAsync(LidarrConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(LidarrConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "Lidarr configuration validation failed"); return Task.FromResult(false); } } public Task SaveContentBlockerConfigAsync(ContentBlockerConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(ContentBlockerConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "ContentBlocker configuration validation failed"); return Task.FromResult(false); } } public Task SaveQueueCleanerConfigAsync(QueueCleanerConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(QueueCleanerConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "QueueCleaner configuration validation failed"); return Task.FromResult(false); } } public Task SaveDownloadCleanerConfigAsync(DownloadCleanerConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(DownloadCleanerConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "DownloadCleaner configuration validation failed"); return Task.FromResult(false); } } public Task SaveDownloadClientConfigAsync(DownloadClientConfig config) { try { config.Validate(); return _configProvider.WriteConfigurationAsync(DownloadClientConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "DownloadClient configuration validation failed"); return Task.FromResult(false); } } public async Task GetIgnoredDownloadsConfigAsync() { var config = await _configProvider.ReadConfigurationAsync(IgnoredDownloadsConfigFile); return config ?? _ignoredDownloadsConfig.CurrentValue; } public Task SaveIgnoredDownloadsConfigAsync(IgnoredDownloadsConfig config) { try { return _configProvider.WriteConfigurationAsync(IgnoredDownloadsConfigFile, config); } catch (Exception ex) { _logger.LogError(ex, "IgnoredDownloads configuration save failed"); return Task.FromResult(false); } } }