using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace ZB.MOM.WW.ScadaBridge.SiteEventLogging;

public static class ServiceCollectionExtensions
{
    /// <summary>
    /// Register site event logging services (recording, purge, query).
    /// </summary>
    /// <param name="services">The DI service collection to register into.</param>
    /// <returns>The same <see cref="IServiceCollection"/> for chaining.</returns>
    public static IServiceCollection AddSiteEventLogging(this IServiceCollection services)
    {
        // The recorder is registered as a concrete singleton and the interface is
        // forwarded to the same instance. The purge and query services depend on the
        // concrete SiteEventLogger directly (they need its lock-guarded WithConnection)
        // rather than downcasting an ISiteEventLogger, which would throw
        // InvalidCastException for any other ISiteEventLogger implementation.
        services.AddSingleton<SiteEventLogger>();
        services.AddSingleton<ISiteEventLogger>(sp => sp.GetRequiredService<SiteEventLogger>());
        services.AddSingleton<IEventLogQueryService, EventLogQueryService>();

        // The purge service still registers on every host
        // node, but it consults an optional SiteEventLogActiveNodeCheck on each
        // tick and early-exits on the standby. The Host registers the real
        // active-node check on site nodes; tests and non-clustered hosts leave
        // it unregistered, and the purge defaults to "always run" (the
        // pre-fix behaviour). Building the service via a factory so the
        // optional delegate flows from DI rather than the constructor default.
        //
        // SiteEventLogReplicationCheck flows the same way and is likewise Host-supplied:
        // it only selects the wording of the purge log line (whether to add the
        // "expect a transient LocalDb oplog backlog" note), and this component has no
        // view of LocalDb:Replication. Unregistered ⇒ no note, matching the default
        // that replication is opt-in and off.
        services.AddHostedService(sp => new EventLogPurgeService(
            sp.GetRequiredService<SiteEventLogger>(),
            sp.GetRequiredService<IOptions<SiteEventLogOptions>>(),
            sp.GetRequiredService<ILogger<EventLogPurgeService>>(),
            sp.GetService<SiteEventLogActiveNodeCheck>(),
            sp.GetService<SiteEventLogReplicationCheck>()));
        return services;
    }

    // NOTE: EventLogHandlerActor is wired up directly in
    // ZB.MOM.WW.ScadaBridge.Host/Actors/AkkaHostedService.cs as a cluster singleton, because the
    // actor must be created inside the ActorSystem with the resolved
    // IEventLogQueryService. There is intentionally no DI helper for that here — a
    // former AddSiteEventLoggingActors placeholder was dead code and has been removed.
}
