using IpcLibrary.Core;
using IpcLibrary.Core.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace IpcLibrary.Services {
    /// <summary>
    /// 方法调用处理器
    /// </summary>
    public class MethodCallHandler {
        private readonly IServiceRegistry _serviceRegistry;

        public MethodCallHandler(IServiceRegistry serviceRegistry) {
            _serviceRegistry = serviceRegistry ?? throw new ArgumentNullException(nameof(serviceRegistry));
        }

        public async Task<MethodCallResponse> HandleMethodCallAsync(MethodCallRequest request) {
            try {
                var service = _serviceRegistry.GetService(request.ServiceName);
                if (service == null) {
                    return new MethodCallResponse {
                        Exception = new IPCException($"服务 '{request.ServiceName}' 未找到")
                    };
                }

                var serviceType = service.GetType();
                MethodInfo method = null;

                // 查找匹配的方法
                if (request.ParameterTypes != null && request.ParameterTypes.Length > 0) {
                    method = serviceType.GetMethod(request.MethodName, request.ParameterTypes);
                } else {
                    // 如果没有提供参数类型，尝试按名称和参数数量匹配
                    var methods = serviceType.GetMethods().Where(m => m.Name == request.MethodName);
                    var paramCount = request.Parameters?.Length ?? 0;
                    method = methods.FirstOrDefault(m => m.GetParameters().Length == paramCount);
                }

                if (method == null) {
                    return new MethodCallResponse {
                        Exception = new IPCException($"方法 '{request.MethodName}' 在服务 '{request.ServiceName}' 中未找到")
                    };
                }

                // 调用方法
                object result;
                if (method.ReturnType == typeof(Task)) {
                    // 异步方法无返回值
                    var task = (Task)method.Invoke(service, request.Parameters);
                    await task;
                    result = null;
                } else if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)) {
                    // 异步方法有返回值
                    var task = (Task)method.Invoke(service, request.Parameters);
                    await task;

                    var resultProperty = task.GetType().GetProperty("Result");
                    result = resultProperty?.GetValue(task);
                } else {
                    // 同步方法
                    result = method.Invoke(service, request.Parameters);
                }

                return new MethodCallResponse {
                    Result = result,
                    ResultType = method.ReturnType
                };
            } catch (TargetInvocationException ex) {
                return new MethodCallResponse {
                    Exception = ex.InnerException ?? ex
                };
            } catch (Exception ex) {
                return new MethodCallResponse {
                    Exception = ex
                };
            }
        }
    }

}
