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

namespace ScadaLink.ClusterInfrastructure;

/// <summary>
/// DI registration for the Cluster Infrastructure component.
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// Registers the Cluster Infrastructure services. This component owns the
    /// cluster <em>configuration contract</em> (<see cref="ClusterOptions"/>); the
    /// Akka.NET bootstrap itself lives in <c>ScadaLink.Host</c>
    /// (see <c>Component-ClusterInfrastructure.md</c>).
    /// <para>
    /// Registering the <see cref="ClusterOptionsValidator"/> means a misconfigured
    /// <c>ScadaLink:Cluster</c> section (e.g. <c>MinNrOfMembers: 2</c> or a quorum
    /// split-brain strategy) throws an <see cref="OptionsValidationException"/> the
    /// first time <see cref="IOptions{TOptions}"/> is resolved, rather than booting
    /// into a broken cluster.
    /// </para>
    /// </summary>
    public static IServiceCollection AddClusterInfrastructure(this IServiceCollection services)
    {
        services.TryAddEnumerable(
            ServiceDescriptor.Singleton<IValidateOptions<ClusterOptions>, ClusterOptionsValidator>());
        return services;
    }

    /// <summary>
    /// Reserved for cluster-infrastructure actor registration. This component does
    /// not register any actors — the Akka.NET bootstrap and actor wiring live in
    /// <c>ScadaLink.Host</c>. The method throws rather than silently returning
    /// success so that any caller assuming this component registers actors fails
    /// fast with a clear cause instead of failing later, far from here.
    /// </summary>
    /// <exception cref="NotImplementedException">Always thrown.</exception>
    public static IServiceCollection AddClusterInfrastructureActors(this IServiceCollection services)
    {
        throw new NotImplementedException(
            "ScadaLink.ClusterInfrastructure registers no actors. The Akka.NET actor system " +
            "bootstrap and all cluster actor registration live in ScadaLink.Host " +
            "(AkkaHostedService). Do not call AddClusterInfrastructureActors().");
    }
}
