using Core.Blueprint.Mongo;
using Core.Blueprint.Mongo.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using static MongoDB.Driver.WriteConcern;
namespace Core.Blueprint.DAL.Mongo.Configuration
{
    /// 
    /// The  class contains extension methods for registering the MongoDB context and configuration settings 
    /// to the  in the dependency injection container.
    /// 
    public static class RegisterBlueprint
    {
        /// 
        /// Adds the MongoDB layer services to the .
        /// Registers the MongoDB context and configuration settings for MongoDB connection, database name, and audience.
        /// 
        /// The  to which the services will be added.
        /// The  used to load MongoDB settings.
        /// The updated  with MongoDB services registered.
        public static IServiceCollection AddMongoLayer(this IServiceCollection services, IConfiguration configuration)
        {
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty;
            
            services.AddSingleton();
            string ConnectionString = configuration.GetSection("ConnectionStrings:MongoDB").Value ?? string.Empty;
            string Databasename = configuration.GetSection("MongoDb:DatabaseName").Value ?? string.Empty;
            string Audience = string.Empty;
            if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase))
            {
                Audience = configuration.GetSection("MongoDb:Audience").Value ?? string.Empty;
            }
            if (string.IsNullOrEmpty(ConnectionString) || string.IsNullOrEmpty(Databasename))
            {
                throw new InvalidOperationException("Mongo connection is not configured correctly.");
            }
            services.Configure(delegate (MongoDbSettings options)
            {
                options.ConnectionString = ConnectionString;
                options.Databasename = Databasename;
                if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase))
                {
                    options.Audience = Audience;
                }
            });
            services.AddSingleton((Func)delegate (IServiceProvider serviceProvider)
            {
                MongoDbSettings value2 = serviceProvider.GetRequiredService>().Value;
                MongoClientSettings mongoClientSettings = MongoClientSettings.FromConnectionString(value2.ConnectionString);
                if (!environment.Equals("Local", StringComparison.OrdinalIgnoreCase)) 
                {
                    mongoClientSettings.Credential = MongoCredential.CreateOidcCredential(new AzureIdentityProvider(value2.Audience));
                }
                    
                return new MongoClient(mongoClientSettings);
            });
            services.AddSingleton(delegate (IServiceProvider serviceProvider)
            {
                MongoDbSettings value = serviceProvider.GetRequiredService>().Value;
                return serviceProvider.GetRequiredService().GetDatabase(value.Databasename);
            });
            services.AddSingleton((Func)((IServiceProvider serviceProvider) => serviceProvider.GetRequiredService>().Value));
            return services;
        }
    }
}