using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.OtOpcUa.Configuration.Services;

namespace ZB.MOM.WW.OtOpcUa.Configuration;

public static class ServiceCollectionExtensions
{
    public const string ConnectionStringName = "ConfigDb";

    /// <summary>
    /// Registers <see cref="IDbContextFactory{TContext}"/> for <see cref="OtOpcUaConfigDbContext"/>
    /// using the connection string named <c>ConfigDb</c> from <see cref="IConfiguration"/>.
    /// </summary>
    /// <param name="services">The service collection to configure.</param>
    /// <param name="configuration">The application configuration.</param>
    /// <returns>The service collection for chaining.</returns>
    public static IServiceCollection AddOtOpcUaConfigDb(this IServiceCollection services, IConfiguration configuration)
    {
        var connectionString = configuration.GetConnectionString(ConnectionStringName)
            ?? throw new InvalidOperationException(
                $"Connection string '{ConnectionStringName}' is required. Add it to appsettings.json or the OTOPCUA_CONFIG_CONNECTION env var.");

        services.AddDbContextFactory<OtOpcUaConfigDbContext>(opt => opt.UseSqlServer(connectionString));

        // AddDbContextFactory registers only the IDbContextFactory<> — it does NOT also register
        // a scoped OtOpcUaConfigDbContext. Config services that take the context directly (e.g.
        // LdapGroupRoleMappingService) need a scoped instance, so bridge one off the factory.
        services.AddScoped(sp => sp.GetRequiredService<IDbContextFactory<OtOpcUaConfigDbContext>>().CreateDbContext());

        // Config-DB services consumed by both the AdminUI (RoleGrants page) and the auth/login
        // host (AuthEndpoints.LoginAsync). Scoped to match the request/render scope of both callers.
        services.AddScoped<ILdapGroupRoleMappingService, LdapGroupRoleMappingService>();

        return services;
    }
}
