using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ZB.MOM.WW.LmxProxy.Client
{
    /// <summary>
    /// Extension methods for registering LmxProxyClient with dependency injection
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// Adds LmxProxyClient services to the service collection
        /// </summary>
        /// <param name="services">The service collection</param>
        /// <param name="configuration">Application configuration</param>
        /// <returns>The service collection for chaining</returns>
        public static IServiceCollection AddLmxProxyClient(this IServiceCollection services, IConfiguration configuration)
        {
            return services.AddLmxProxyClient(configuration, "LmxProxy");
        }

        /// <summary>
        /// Adds LmxProxyClient services to the service collection with a specific configuration section
        /// </summary>
        /// <param name="services">The service collection</param>
        /// <param name="configuration">Application configuration</param>
        /// <param name="configurationSection">Name of the configuration section</param>
        /// <returns>The service collection for chaining</returns>
        public static IServiceCollection AddLmxProxyClient(
            this IServiceCollection services,
            IConfiguration configuration,
            string configurationSection)
        {
            services.AddSingleton<ILmxProxyClientFactory, LmxProxyClientFactory>();

            // Register a singleton client with default configuration
            services.AddSingleton<LmxProxyClient>(provider =>
            {
                ILmxProxyClientFactory factory = provider.GetRequiredService<ILmxProxyClientFactory>();
                return factory.CreateClient(configurationSection);
            });

            return services;
        }

        /// <summary>
        /// Adds LmxProxyClient services to the service collection with custom configuration
        /// </summary>
        /// <param name="services">The service collection</param>
        /// <param name="configureClient">Action to configure the client builder</param>
        /// <returns>The service collection for chaining</returns>
        public static IServiceCollection AddLmxProxyClient(
            this IServiceCollection services,
            Action<LmxProxyClientBuilder> configureClient)
        {
            services.AddSingleton<ILmxProxyClientFactory, LmxProxyClientFactory>();

            // Register a singleton client with custom configuration
            services.AddSingleton<LmxProxyClient>(provider =>
            {
                ILmxProxyClientFactory factory = provider.GetRequiredService<ILmxProxyClientFactory>();
                return factory.CreateClient(configureClient);
            });

            return services;
        }

        /// <summary>
        /// Adds LmxProxyClient services to the service collection with scoped lifetime
        /// </summary>
        /// <param name="services">The service collection</param>
        /// <param name="configuration">Application configuration</param>
        /// <returns>The service collection for chaining</returns>
        public static IServiceCollection AddScopedLmxProxyClient(
            this IServiceCollection services,
            IConfiguration configuration)
        {
            services.AddSingleton<ILmxProxyClientFactory, LmxProxyClientFactory>();

            // Register a scoped client
            services.AddScoped<LmxProxyClient>(provider =>
            {
                ILmxProxyClientFactory factory = provider.GetRequiredService<ILmxProxyClientFactory>();
                return factory.CreateClient();
            });

            return services;
        }

        /// <summary>
        /// Adds named LmxProxyClient services to the service collection
        /// </summary>
        /// <param name="services">The service collection</param>
        /// <param name="name">Name for the client</param>
        /// <param name="configureClient">Action to configure the client builder</param>
        /// <returns>The service collection for chaining</returns>
        public static IServiceCollection AddNamedLmxProxyClient(
            this IServiceCollection services,
            string name,
            Action<LmxProxyClientBuilder> configureClient)
        {
            services.AddSingleton<ILmxProxyClientFactory, LmxProxyClientFactory>();

            // Register a keyed singleton
            services.AddKeyedSingleton<LmxProxyClient>(name, (provider, _) =>
            {
                ILmxProxyClientFactory factory = provider.GetRequiredService<ILmxProxyClientFactory>();
                return factory.CreateClient(configureClient);
            });

            return services;
        }
    }

    /// <summary>
    /// Configuration options for LmxProxyClient
    /// </summary>
    public class LmxProxyClientOptions
    {
        /// <summary>
        /// Gets or sets the host address
        /// </summary>
        public string Host { get; set; } = "localhost";

        /// <summary>
        /// Gets or sets the port number
        /// </summary>
        public int Port { get; set; } = 5050;

        /// <summary>
        /// Gets or sets the API key
        /// </summary>
        public string? ApiKey { get; set; }

        /// <summary>
        /// Gets or sets the timeout duration
        /// </summary>
        public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);

        /// <summary>
        /// Gets or sets whether to use SSL
        /// </summary>
        public bool UseSsl { get; set; }

        /// <summary>
        /// Gets or sets the certificate path for SSL
        /// </summary>
        public string? CertificatePath { get; set; }

        /// <summary>
        /// Gets or sets whether to enable metrics
        /// </summary>
        public bool EnableMetrics { get; set; }

        /// <summary>
        /// Gets or sets the correlation ID header name
        /// </summary>
        public string? CorrelationIdHeader { get; set; }

        /// <summary>
        /// Gets or sets the retry configuration
        /// </summary>
        public RetryOptions? Retry { get; set; }
    }

    /// <summary>
    /// Retry configuration options
    /// </summary>
    public class RetryOptions
    {
        /// <summary>
        /// Gets or sets the maximum number of retry attempts
        /// </summary>
        public int MaxAttempts { get; set; } = 3;

        /// <summary>
        /// Gets or sets the delay between retries
        /// </summary>
        public TimeSpan Delay { get; set; } = TimeSpan.FromSeconds(1);
    }
}
