using CloudBuilder.Core.Application.Builders;
using CloudBuilder.Core.Application.Packs;
using CloudBuilder.Core.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace CloudBuilder.Core.DependencyInjection.Request
{
    [PackLevel(35)]
    public class RequestPack : CloudBuilderPack
    {
        /// <summary>
        /// 获取 模块级别
        /// </summary>
        public override PackLevel Level => PackLevel.Business;

        /// <summary>
        /// 获取 模块启动顺序，模块启动的顺序先按级别启动，级别内部再按此顺序启动
        /// </summary>
        public override int Order => 2;

        /// <summary>
        /// 将请求添加到依赖注入服务容器中
        /// </summary>
        /// <param name="services">依赖注入服务容器</param>
        /// <returns></returns>
        public override IServiceCollection AddServices(IServiceCollection services, CloudBuilderBuilder builder)
        {
            //注入请求
            services.AddHttpClient();

            var baseType = typeof(IRequest);

            var allAssemblies = CloudBuilderBuilder.GetAssemblies();

            var types = allAssemblies
                .SelectMany(a => a.DefinedTypes)
                .Select(type => type.AsType())
                .Where(type => type != baseType && type.HasImplementedRawGeneric(baseType))
                .Where(x => x.IsClass).ToList();

            /*TryAddKeyedScoped	Scoped（作用域）	每个请求（或作用域）内是同一个实例，不同请求之间不同。
             * 在 WinForms 应用程序中，依赖注入（DI）的 作用域（Scoped）生命周期 不像 ASP.NET Core 那样自动按 HTTP 请求划分作用域，
             * 而是需要手动管理作用域。
             * 在 WinForms 应用程序中，如果没有使用手动管理作用域，那么相关于全局作用域，类似于单例又不同于单例(手动管理作用域)。
             * 在 WinForms 中使用 Scoped 服务
            using (var scope1 = ServiceProvider.CreateScope())
            {
                AuthRequest authRequest = scope1.ServiceProvider.GetRequiredKeyedService<AuthRequest>(typeof(AuthRequest).Name);            
                string pubKeyc = await authRequest.GetRsaPublicKey();
            }
            //下面的对应的是上面的调用方式
            //services.TryAddKeyedScoped(implementType, implementType.Name);
            现在修改为下面这样调用方式 IServiceRequest serviceRequest
            // IAuthRequest authRequest = ServiceProvider.GetService<IAuthRequest>()!;
            */
            foreach (var implementType in types)
            {
                //AuthRequest要对应AuthService的方法，所以注入名字
                services.TryAddKeyedScoped(implementType, implementType.Name);

                //ServiceRequest(注入接口)
                
                services.TryAddScoped(implementType.GetInterfaces().FirstOrDefault(), implementType);
            }

            //因为每个用户都是独立的，因此不能注册为单一的
            //services.TryAddSingleton<IContext, LoginContext>();
            //客户端的生命周期是静态的，唯一的

            //注册为作用域生命周期
            services.TryAddScoped<IContext, LoginContext>();

            return services;
        }
    }
}