using Microsoft.Extensions.Configuration;

namespace ZB.MOM.WW.LmxProxy.Client;

/// <summary>
/// Factory for creating <see cref="LmxProxyClient"/> instances.
/// </summary>
public interface ILmxProxyClientFactory
{
    /// <summary>Creates a client from the default "LmxProxy" configuration section.</summary>
    LmxProxyClient CreateClient();

    /// <summary>Creates a client from a named configuration section.</summary>
    LmxProxyClient CreateClient(string configName);

    /// <summary>Creates a client using a builder configuration action.</summary>
    LmxProxyClient CreateClient(Action<LmxProxyClientBuilder> builderAction);
}

/// <summary>
/// Default implementation of <see cref="ILmxProxyClientFactory"/> that reads from IConfiguration.
/// </summary>
public class LmxProxyClientFactory : ILmxProxyClientFactory
{
    private readonly IConfiguration _configuration;

    /// <summary>Creates a new factory with the specified configuration.</summary>
    public LmxProxyClientFactory(IConfiguration configuration)
    {
        _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
    }

    /// <inheritdoc />
    public LmxProxyClient CreateClient() => CreateClient("LmxProxy");

    /// <inheritdoc />
    public LmxProxyClient CreateClient(string configName)
    {
        IConfigurationSection section = _configuration.GetSection(configName);
        var options = new LmxProxyClientOptions();
        section.Bind(options);
        return BuildFromOptions(options);
    }

    /// <inheritdoc />
    public LmxProxyClient CreateClient(Action<LmxProxyClientBuilder> builderAction)
    {
        var builder = new LmxProxyClientBuilder();
        builderAction(builder);
        return builder.Build();
    }

    private static LmxProxyClient BuildFromOptions(LmxProxyClientOptions options)
    {
        var builder = new LmxProxyClientBuilder()
            .WithHost(options.Host)
            .WithPort(options.Port)
            .WithTimeout(options.Timeout)
            .WithRetryPolicy(options.Retry.MaxAttempts, options.Retry.Delay);

        if (!string.IsNullOrEmpty(options.ApiKey))
            builder.WithApiKey(options.ApiKey);

        if (options.EnableMetrics)
            builder.WithMetrics();

        if (!string.IsNullOrEmpty(options.CorrelationIdHeader))
            builder.WithCorrelationIdHeader(options.CorrelationIdHeader);

        if (options.UseSsl)
        {
            builder.WithTlsConfiguration(new ClientTlsConfiguration
            {
                UseTls = true,
                ServerCaCertificatePath = options.CertificatePath
            });
        }

        return builder.Build();
    }
}
