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; }
}
}