using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using ZB.MOM.WW.Configuration;

namespace ZB.MOM.WW.MxGateway.Server.Configuration;

public static class GatewayConfigurationServiceCollectionExtensions
{
    /// <summary>Registers gateway configuration services in the dependency injection container.</summary>
    /// <param name="services">The service collection.</param>
    /// <param name="configuration">The configuration to bind gateway options from.</param>
    /// <returns>The service collection for chaining.</returns>
    public static IServiceCollection AddGatewayConfiguration(
        this IServiceCollection services, IConfiguration configuration)
    {
        // GatewayOptionsValidator depends on IHostEnvironment to gate the production-only rules.
        // The real host and the apikey CLI both build through WebApplicationBuilder,
        // which registers IHostEnvironment before this call — so TryAdd is a no-op there. Minimal
        // containers (unit tests, tooling) have none; fall back to a non-production environment so
        // the validator still activates and the production guards stay off outside a real
        // deployment (the fail-fast guards only make sense against a real host environment).
        services.TryAddSingleton<IHostEnvironment>(new FallbackHostEnvironment());

        services.AddValidatedOptions<GatewayOptions, GatewayOptionsValidator>(
            configuration, GatewayOptions.SectionName);

        services.AddSingleton<IGatewayConfigurationProvider, GatewayConfigurationProvider>();

        return services;
    }

    /// <summary>
    /// Non-production <see cref="IHostEnvironment"/> used only when no real host registered one
    /// (minimal test/tooling containers). The real host's registration always wins via TryAdd.
    /// </summary>
    private sealed class FallbackHostEnvironment : IHostEnvironment
    {
        /// <summary>Gets or sets the name of the environment; defaults to <see cref="Environments.Development"/>.</summary>
        public string EnvironmentName { get; set; } = Environments.Development;

        /// <summary>Gets or sets the name of the application.</summary>
        public string ApplicationName { get; set; } = typeof(FallbackHostEnvironment).Assembly.GetName().Name ?? "MxGateway";

        /// <summary>Gets or sets the absolute path to the content root directory.</summary>
        public string ContentRootPath { get; set; } = AppContext.BaseDirectory;

        /// <summary>Gets or sets the file provider for the content root.</summary>
        public IFileProvider ContentRootFileProvider { get; set; } = new NullFileProvider();
    }
}
