using System.Reflection;
using JiShe.CollectBus.Protocol.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Modularity;

namespace JiShe.CollectBus.Protocol.T37612012
{
    public class CollectBusProtocolT37612012Module : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddKeyedSingleton<IProtocolPlugin, T37612012ProtocolPlugin>(nameof(T37612012ProtocolPlugin));

            // TODO:先用之前的策略注册方式，后续验证后采用LoadAnalysisStrategy
            RegisterProtocolAnalysis(context.Services);
            //LoadAnalysisStrategy(context.Services);
        }

        public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
        {
            Console.WriteLine($"{nameof(T37612012ProtocolPlugin)} OnApplicationInitializationAsync");
            var standardProtocol = context.ServiceProvider.GetRequiredKeyedService<IProtocolPlugin>(nameof(T37612012ProtocolPlugin));
            await standardProtocol.LoadAsync();
        }

        public override void OnApplicationShutdown(ApplicationShutdownContext context)
        {
            Console.WriteLine($"{nameof(T37612012ProtocolPlugin)} OnApplicationShutdown");
            base.OnApplicationShutdown(context);
        }

        public void LoadAnalysisStrategy(IServiceCollection services)
        {
            services.AddTransient<AnalysisStrategyContext>();
            var assembly = Assembly.GetExecutingAssembly();
            var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<>)));
            foreach (var analysisStrategyType in analysisStrategyTypes)
            {
                var service = analysisStrategyType.GetInterfaces().First();
                services.AddKeyedSingleton(service, analysisStrategyType.Name, analysisStrategyType);
            }
        }

        public void RegisterProtocolAnalysis(IServiceCollection services)
        {
            // 扫描并注册所有策略
            var strategyMetadata = new Dictionary<(string, Type), Type>();
            services.AddTransient<AnalysisStrategyContext>();

            // 批量注册
            var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            if (string.IsNullOrWhiteSpace(assemblyPath))
            {
                return;
            }
            var dllFiles = Directory.GetFiles(Path.Combine(assemblyPath, "Plugins"), "*.dll");
            foreach (var file in dllFiles)
            {
                // 跳过已加载的程序集
                var assemblyName = AssemblyName.GetAssemblyName(file);
                var existingAssembly = AppDomain.CurrentDomain.GetAssemblies()
                    .FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName);
                var assembly = existingAssembly ?? Assembly.LoadFrom(file);
                // 实现IAnalysisStrategy接口
                var analysisStrategyTypes = assembly.GetTypes().Where(t => !t.IsAbstract && !t.IsInterface && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IAnalysisStrategy<>)));
                if (!analysisStrategyTypes.Any())
                    continue;
                foreach (var analysisStrategyType in analysisStrategyTypes)
                {
                    // 通过反射获取静态元数据  
                    var strategyType = analysisStrategyType.Name;
                    var genericArgs = analysisStrategyType.GetInterface($"IAnalysisStrategy`1")!.GetGenericArguments();
                    var inputType = genericArgs[0];
                    // 注册策略实现
                    services.AddTransient(analysisStrategyType);
                    strategyMetadata[(strategyType, inputType)] = analysisStrategyType;

                }
            }

            // 注册元数据字典
            services.AddSingleton(strategyMetadata);

            // 注册策略解析工厂
            services.AddTransient<Func<string, Type, object?>>(provider => (name, inputType) =>
            {
                var metadata = provider.GetRequiredService<Dictionary<(string, Type), Type>>();
                if (metadata.TryGetValue((name, inputType), out var strategyType))
                {
                    return provider.GetRequiredService(strategyType);
                }
                else
                {
                    var logger = provider.GetRequiredService<ILogger<AnalysisStrategyContext>>();
                    logger.LogWarning($"未能找到解析策略：{name}-{inputType}");
                    return null;
                }
            });
        }
    }
}



