using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer;

/// <summary>
/// DI registration extensions for the Data Connection Layer.
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>Registers Data Connection Layer options and core services.</summary>
    /// <param name="services">The DI service collection to register into.</param>
    /// <returns>The same <paramref name="services"/> instance for chaining.</returns>
    public static IServiceCollection AddDataConnectionLayer(this IServiceCollection services)
    {
        // Canonical section is ScadaBridge:DataConnection — the section every real
        // appsettings actually writes (arch-review 08 round 2 NF8). The Host used to
        // supply the real values via a duplicate Configure<> binding; that duplicate is
        // gone, so AddDataConnectionLayer must bind the canonical section itself.
        services.AddOptions<DataConnectionOptions>()
            .BindConfiguration("ScadaBridge:DataConnection")
            .ValidateOnStart();
        services.TryAddEnumerable(
            ServiceDescriptor.Singleton<IValidateOptions<DataConnectionOptions>, DataConnectionOptionsValidator>());

        // OpcUaGlobalOptions / MxGatewayGlobalOptions carry only string identity/path
        // fields (no numeric or duration knobs), so there is nothing to range-validate
        // — no dedicated validator is registered for them. Canonical sections are
        // ScadaBridge:OpcUa / ScadaBridge:MxGateway (NF8): the bare "OpcUa"/"MxGateway"
        // sections exist in no appsettings, so binding them read nothing.
        services.AddOptions<OpcUaGlobalOptions>()
            .BindConfiguration("ScadaBridge:OpcUa");

        services.AddOptions<MxGatewayGlobalOptions>()
            .BindConfiguration("ScadaBridge:MxGateway");

        // Register the factory for protocol extensibility
        services.AddSingleton<IDataConnectionFactory, DataConnectionFactory>();

        return services;
    }

    /// <summary>Placeholder for actor registration; Data Connection Layer actors are created inside the ActorSystem.</summary>
    /// <param name="services">The DI service collection.</param>
    /// <returns>The same <paramref name="services"/> instance for chaining.</returns>
    public static IServiceCollection AddDataConnectionLayerActors(this IServiceCollection services)
    {
        // Actor registration happens in AkkaHostedService or SiteCommunicationActor setup.
        // DataConnectionManagerActor and DataConnectionActor instances are created by the actor system.
        return services;
    }
}
