using System; using System.IO; using Microsoft.Extensions.Logging; namespace ZB.MOM.WW.LmxProxy.Client { /// /// Builder for creating configured instances of LmxProxyClient /// public class LmxProxyClientBuilder { private string? _host; private int _port = 5050; private string? _apiKey; private ILogger? _logger; private TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); private int _maxRetryAttempts = 3; private TimeSpan _retryDelay = TimeSpan.FromSeconds(1); private bool _enableMetrics; private string? _correlationIdHeader; private ClientTlsConfiguration? _tlsConfiguration; /// /// Sets the host address for the LmxProxy service /// /// The host address /// The builder instance for method chaining public LmxProxyClientBuilder WithHost(string host) { if (string.IsNullOrWhiteSpace(host)) throw new ArgumentException("Host cannot be null or empty", nameof(host)); _host = host; return this; } /// /// Sets the port for the LmxProxy service /// /// The port number /// The builder instance for method chaining public LmxProxyClientBuilder WithPort(int port) { if (port < 1 || port > 65535) throw new ArgumentOutOfRangeException(nameof(port), "Port must be between 1 and 65535"); _port = port; return this; } /// /// Sets the API key for authentication /// /// The API key /// The builder instance for method chaining public LmxProxyClientBuilder WithApiKey(string apiKey) { _apiKey = apiKey; return this; } /// /// Sets the logger instance /// /// The logger /// The builder instance for method chaining public LmxProxyClientBuilder WithLogger(ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); return this; } /// /// Sets the default timeout for operations /// /// The timeout duration /// The builder instance for method chaining public LmxProxyClientBuilder WithTimeout(TimeSpan timeout) { if (timeout <= TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeout), "Timeout must be positive"); if (timeout > TimeSpan.FromMinutes(10)) throw new ArgumentOutOfRangeException(nameof(timeout), "Timeout cannot exceed 10 minutes"); _defaultTimeout = timeout; return this; } /// /// Enables SSL/TLS with the specified certificate /// /// Path to the certificate file /// The builder instance for method chaining public LmxProxyClientBuilder WithSslCredentials(string? certificatePath = null) { _tlsConfiguration ??= new ClientTlsConfiguration(); _tlsConfiguration.UseTls = true; _tlsConfiguration.ServerCaCertificatePath = string.IsNullOrWhiteSpace(certificatePath) ? null : certificatePath; return this; } /// /// Applies a full TLS configuration to the client. /// /// The TLS configuration to apply. /// The builder instance for method chaining. public LmxProxyClientBuilder WithTlsConfiguration(ClientTlsConfiguration configuration) { _tlsConfiguration = configuration ?? throw new ArgumentNullException(nameof(configuration)); return this; } /// /// Sets the retry configuration /// /// Maximum number of retry attempts /// Delay between retries /// The builder instance for method chaining public LmxProxyClientBuilder WithRetryPolicy(int maxAttempts, TimeSpan retryDelay) { if (maxAttempts <= 0) throw new ArgumentOutOfRangeException(nameof(maxAttempts), "Max attempts must be positive"); if (retryDelay <= TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(retryDelay), "Retry delay must be positive"); _maxRetryAttempts = maxAttempts; _retryDelay = retryDelay; return this; } /// /// Enables metrics collection /// /// The builder instance for method chaining public LmxProxyClientBuilder WithMetrics() { _enableMetrics = true; return this; } /// /// Sets the correlation ID header name for request tracing /// /// The header name for correlation ID /// The builder instance for method chaining public LmxProxyClientBuilder WithCorrelationIdHeader(string headerName) { if (string.IsNullOrEmpty(headerName)) throw new ArgumentException("Header name cannot be null or empty", nameof(headerName)); _correlationIdHeader = headerName; return this; } /// /// Builds the configured LmxProxyClient instance /// /// A configured LmxProxyClient instance public LmxProxyClient Build() { if (string.IsNullOrWhiteSpace(_host)) throw new InvalidOperationException("Host must be specified"); ValidateTlsConfiguration(); var client = new LmxProxyClient(_host, _port, _apiKey, _tlsConfiguration, _logger) { DefaultTimeout = _defaultTimeout }; // Store additional configuration for future use client.SetBuilderConfiguration(new ClientConfiguration { MaxRetryAttempts = _maxRetryAttempts, RetryDelay = _retryDelay, EnableMetrics = _enableMetrics, CorrelationIdHeader = _correlationIdHeader }); return client; } private void ValidateTlsConfiguration() { if (_tlsConfiguration?.UseTls != true) { return; } if (!string.IsNullOrWhiteSpace(_tlsConfiguration.ServerCaCertificatePath) && !File.Exists(_tlsConfiguration.ServerCaCertificatePath)) { throw new FileNotFoundException( $"Certificate file not found: {_tlsConfiguration.ServerCaCertificatePath}", _tlsConfiguration.ServerCaCertificatePath); } if (!string.IsNullOrWhiteSpace(_tlsConfiguration.ClientCertificatePath) && !File.Exists(_tlsConfiguration.ClientCertificatePath)) { throw new FileNotFoundException( $"Client certificate file not found: {_tlsConfiguration.ClientCertificatePath}", _tlsConfiguration.ClientCertificatePath); } if (!string.IsNullOrWhiteSpace(_tlsConfiguration.ClientKeyPath) && !File.Exists(_tlsConfiguration.ClientKeyPath)) { throw new FileNotFoundException( $"Client key file not found: {_tlsConfiguration.ClientKeyPath}", _tlsConfiguration.ClientKeyPath); } } } /// /// Internal configuration class for storing builder settings /// internal class ClientConfiguration { /// /// Gets or sets the maximum number of retry attempts. /// public int MaxRetryAttempts { get; set; } /// /// Gets or sets the retry delay. /// public TimeSpan RetryDelay { get; set; } /// /// Gets or sets a value indicating whether metrics are enabled. /// public bool EnableMetrics { get; set; } /// /// Gets or sets the correlation ID header name. /// public string? CorrelationIdHeader { get; set; } } }