using System;
using System.Linq;
using Microsoft.Extensions.Configuration;

namespace ZB.MOM.WW.LmxProxy.Client
{
    /// <summary>
    /// Factory interface for creating LmxProxyClient instances
    /// </summary>
    public interface ILmxProxyClientFactory
    {
        /// <summary>
        /// Creates a new LmxProxyClient instance with default configuration
        /// </summary>
        /// <returns>A configured LmxProxyClient instance</returns>
        LmxProxyClient CreateClient();

        /// <summary>
        /// Creates a new LmxProxyClient instance with custom configuration
        /// </summary>
        /// <param name="configurationName">Name of the configuration section to use</param>
        /// <returns>A configured LmxProxyClient instance</returns>
        LmxProxyClient CreateClient(string configurationName);

        /// <summary>
        /// Creates a new LmxProxyClient instance using a builder
        /// </summary>
        /// <param name="builderAction">Action to configure the builder</param>
        /// <returns>A configured LmxProxyClient instance</returns>
        LmxProxyClient CreateClient(Action<LmxProxyClientBuilder> builderAction);
    }

    /// <summary>
    /// Default implementation of ILmxProxyClientFactory
    /// </summary>
    public class LmxProxyClientFactory : ILmxProxyClientFactory
    {
        private readonly IConfiguration _configuration;

        /// <summary>
        /// Initializes a new instance of the LmxProxyClientFactory
        /// </summary>
        /// <param name="configuration">Application configuration</param>
        public LmxProxyClientFactory(IConfiguration configuration)
        {
            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        }

        /// <summary>
        /// Creates a new LmxProxyClient instance with default configuration
        /// </summary>
        /// <returns>A configured LmxProxyClient instance</returns>
        public LmxProxyClient CreateClient()
        {
            return CreateClient("LmxProxy");
        }

        /// <summary>
        /// Creates a new LmxProxyClient instance with custom configuration
        /// </summary>
        /// <param name="configurationName">Name of the configuration section to use</param>
        /// <returns>A configured LmxProxyClient instance</returns>
        public LmxProxyClient CreateClient(string configurationName)
        {
            IConfigurationSection section = _configuration.GetSection(configurationName);
            if (!section.GetChildren().Any() && section.Value == null)
            {
                throw new InvalidOperationException($"Configuration section '{configurationName}' not found");
            }

            var builder = new LmxProxyClientBuilder();

            // Configure from appsettings
            string? host = section["Host"];
            if (!string.IsNullOrEmpty(host))
            {
                builder.WithHost(host);
            }

            if (int.TryParse(section["Port"], out int port))
            {
                builder.WithPort(port);
            }

            string? apiKey = section["ApiKey"];
            if (!string.IsNullOrEmpty(apiKey))
            {
                builder.WithApiKey(apiKey);
            }

            if (TimeSpan.TryParse(section["Timeout"], out TimeSpan timeout))
            {
                builder.WithTimeout(timeout);
            }

            // Retry configuration
            IConfigurationSection? retrySection = section.GetSection("Retry");
            if (retrySection != null && (retrySection.GetChildren().Any() || retrySection.Value != null))
            {
                if (int.TryParse(retrySection["MaxAttempts"], out int maxAttempts) &&
                    TimeSpan.TryParse(retrySection["Delay"], out TimeSpan retryDelay))
                {
                    builder.WithRetryPolicy(maxAttempts, retryDelay);
                }
            }

            // SSL configuration
            bool useSsl = section.GetValue<bool>("UseSsl");
            if (useSsl)
            {
                string? certificatePath = section["CertificatePath"];
                builder.WithSslCredentials(certificatePath);
            }

            // Metrics configuration
            if (section.GetValue<bool>("EnableMetrics"))
            {
                builder.WithMetrics();
            }

            // Correlation ID configuration
            string? correlationHeader = section["CorrelationIdHeader"];
            if (!string.IsNullOrEmpty(correlationHeader))
            {
                builder.WithCorrelationIdHeader(correlationHeader);
            }

            // Logger is optional - don't set a default one

            return builder.Build();
        }

        /// <summary>
        /// Creates a new LmxProxyClient instance using a builder
        /// </summary>
        /// <param name="builderAction">Action to configure the builder</param>
        /// <returns>A configured LmxProxyClient instance</returns>
        public LmxProxyClient CreateClient(Action<LmxProxyClientBuilder> builderAction)
        {
            ArgumentNullException.ThrowIfNull(builderAction);

            var builder = new LmxProxyClientBuilder();
            builderAction(builder);

            // Logger is optional - caller can set it via builderAction if needed

            return builder.Build();
        }
    }
}
