using System.Reflection;
using System.Runtime.Loader;
using Autofac;
using Autofac.Extras.Quartz;
using ce.autofac.extension;
using Infrastructure.Cache;
using Infrastructure.Extensions.AutofacManager;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyModel;
using OpenAuth.App.Interface;
using OpenAuth.App.SSO;
using OpenAuth.Repository;
using SqlSugar;

namespace OpenAuth.App
{
    public static class AutofacExt
    {
        public static void InitAutofac(ContainerBuilder builder)
        {
            //注册数据库基础操作和工作单元
            builder.RegisterGeneric(typeof(SugarRepositiry<>)).As(typeof(ISimpleClient<>)).InstancePerLifetimeScope();
            //builder.RegisterGeneric(typeof(SimpleClient<>)).As(typeof(ISimpleClient<>)).InstancePerLifetimeScope();
            //builder.RegisterGeneric(typeof(SugarRepositiry<>)).As(typeof(ISugarRepositiry<>)).InstancePerLifetimeScope();
            //builder.RegisterGeneric(typeof(SugarUnitOfWork<>)).As(typeof(ISugarUnitOfWork<>)).InstancePerLifetimeScope();

            //注入授权
            builder.RegisterType(typeof(LocalAuth)).As(typeof(IAuth)).InstancePerLifetimeScope();

            //注册app层
            builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).InstancePerLifetimeScope();

            builder.RegisterType(typeof(RedisCacheContext)).As(typeof(ICacheContext)).InstancePerLifetimeScope();
            //builder.RegisterType(typeof(CacheContext)).As(typeof(ICacheContext));
            builder.RegisterType(typeof(HttpContextAccessor)).As(typeof(IHttpContextAccessor))
                .InstancePerLifetimeScope();
            try
            {
                foreach (Assembly assembly in ce.autofac.extension.Extensions.GetAssemblies())
                {
                    foreach (Type type in assembly.GetTypes().Where((Func<Type, bool>)(t =>
                                 typeof(IBLL).IsAssignableFrom(t) &&
                                 t.GetCustomAttribute<BLLNameAttribute>() != null)))
                    {
                        BLLNameAttribute customAttribute = type.GetCustomAttribute<BLLNameAttribute>();
                        Type serviceType =
                            type.GetInterfaces().FirstOrDefault(
                                (Func<Type, bool>)(t => typeof(IBLL).IsAssignableFrom(t)));
                        if (serviceType != null)
                        {
                            builder.RegisterType(type).AsImplementedInterfaces()
                                .Named(customAttribute.BLLName, serviceType);
                            builder.RegisterType(type).Named(customAttribute.BLLName, type);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            InitDependency(builder);

            builder.RegisterModule(new QuartzAutofacFactoryModule());
        }


        /// <summary>
        /// 注入所有继承了IDependency接口
        /// </summary>
        /// <param name="builder"></param>
        private static void InitDependency(ContainerBuilder builder)
        {
            Type baseType = typeof(IDependency);
            var compilationLibrary = DependencyContext.Default
                .CompileLibraries
                .Where(x => !x.Serviceable
                            && x.Type == "project")
                .ToList();
            var count1 = compilationLibrary.Count;
            List<Assembly> assemblyList = new List<Assembly>();

            foreach (var _compilation in compilationLibrary)
            {
                try
                {
                    assemblyList.Add(
                        AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(_compilation.Name)));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(_compilation.Name + ex.Message);
                }
            }

            builder.RegisterAssemblyTypes(assemblyList.ToArray())
                .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
                .AsSelf().AsImplementedInterfaces()
                .InstancePerLifetimeScope();
        }
    }
}