using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;

namespace JiShe.CollectBus.DynamicModule
{
    /// <summary>
    /// 动态模块管理器的实现
    /// </summary>
    public class DynamicModuleManager : IDynamicModuleManager, ISingletonDependency
    {
        private readonly IModuleContainer _moduleContainer;
        private readonly IServiceProvider _serviceProvider;

        public DynamicModuleManager(
            IModuleContainer moduleContainer,
            IServiceProvider serviceProvider)
        {
            _moduleContainer = moduleContainer;
            _serviceProvider = serviceProvider;
        }

        public Type[] GetRegisteredModuleTypes()
        {
            return _moduleContainer.Modules.Select(m => m.Type).ToArray();
        }

        public async Task ReinitializeModuleAsync(Type moduleType)
        {
            if (!typeof(IAbpModule).IsAssignableFrom(moduleType))
            {
                throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType));
            }

            var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type.Name == moduleType.Name);
            if (moduleDescriptor == null)
            {
                throw new InvalidOperationException($"找不到类型为 {moduleType.FullName} 的模块");
            }

            var module = moduleDescriptor.Instance;

            await CallModuleMethodAsync(module, "OnApplicationShutdown", [new ApplicationShutdownContext(_serviceProvider)]);
            var configureServicesMethod = moduleType.GetMethod("ConfigureServices",BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
            if (configureServicesMethod != null)
            {
                var serviceConfigurationContext = CreateServiceConfigurationContext();
                configureServicesMethod.Invoke(module, [serviceConfigurationContext]);
            }
            await CallModuleMethodAsync(module, "OnApplicationInitializationAsync", [new ApplicationInitializationContext(_serviceProvider)]);
        }

        public async Task UnloadModuleAsync(Type moduleType)
        {
            if (!typeof(IAbpModule).IsAssignableFrom(moduleType))
            {
                throw new ArgumentException($"指定的类型 {moduleType.FullName} 不是有效的ABP模块类型", nameof(moduleType));
            }

            var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type.Name == moduleType.Name);
            if (moduleDescriptor == null)
            {
                throw new InvalidOperationException($"找不到类型为 {moduleType.FullName} 的模块");
            }

            var module = moduleDescriptor.Instance;

            await CallModuleMethodAsync(module, "OnApplicationShutdown", new object[] { new ApplicationShutdownContext(_serviceProvider) });
            moduleDescriptor.GetType().GetProperty("IsUnloaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?
                .SetValue(moduleDescriptor, true);
        }

        public bool IsModuleLoaded(Type moduleType)
        {
            var moduleDescriptor = _moduleContainer.Modules.FirstOrDefault(m => m.Type == moduleType);
            if (moduleDescriptor == null)
            {
                return false;
            }

            // 检查模块是否已被标记为卸载
            var isUnloaded = (bool?)moduleDescriptor.GetType().GetProperty("IsUnloaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?
                .GetValue(moduleDescriptor) ?? false;

            return !isUnloaded;
        }

        public Type GetModuleTypeByName(string moduleName)
        {
            return _moduleContainer.Modules
                .FirstOrDefault(m => m.Type.Name == moduleName || m.Type.FullName == moduleName)?
                .Type;
        }

        private async Task CallModuleMethodAsync(IAbpModule module, string methodName, object[] parameters)
        {
            var method = module.GetType().GetMethod(methodName);
            if (method == null)
            {
                return;
            }

            if (method.ReturnType == typeof(Task))
            {
                await (Task)method.Invoke(module, parameters);
            }
            else
            {
                method.Invoke(module, parameters);
            }
        }

        private ServiceConfigurationContext CreateServiceConfigurationContext()
        {
            // 反射获取内部构造函数
            var contextType = typeof(ServiceConfigurationContext);
            var constructor = contextType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault();

            if (constructor != null)
            {
                // 创建新的服务集合并添加现有服务
                var services = new ServiceCollection();
                foreach (var service in ((IServiceCollection)_serviceProvider.GetService<IServiceCollection>()) ?? new ServiceCollection())
                {
                    services.Add(service);
                }

                return (ServiceConfigurationContext)constructor.Invoke([services]);
            }

            // 如果反射失败，使用备选方案
            try
            {
                var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
                var services = new ServiceCollection();

                var context = Activator.CreateInstance(contextType, bindingFlags, null, null, null);

                var servicesProperty = contextType.GetProperty("Services");
                servicesProperty?.SetValue(context, services);

                return (ServiceConfigurationContext)context;
            }
            catch
            {
                throw new InvalidOperationException("无法创建ServiceConfigurationContext。这可能是由于与ABP框架版本不兼容造成的。");
            }
        }
    }
}
