using System.Reflection;
using System.Runtime.CompilerServices;

namespace AyCode.Services.Server.SignalRs;

public static class ExtensionMethods
{
    /// <summary>
    /// Invokes a method and properly unwraps Task/Task&lt;T&gt; results.
    /// Handles both async methods and methods returning Task directly (e.g., Task.FromResult).
    /// </summary>
    public static object? InvokeMethod(this MethodInfo methodInfo, object obj, params object[]? parameters)
    {
        var result = methodInfo.Invoke(obj, parameters);
        
        if (result == null)
            return null;

        // Check if result is a Task (this handles both async methods AND Task.FromResult)
        if (result is Task task)
        {
            // Wait for task completion
            task.GetAwaiter().GetResult();
            
            // Check if it's Task<T> to extract the actual result
            var taskType = task.GetType();
            if (taskType.IsGenericType)
            {
                // Get the Result property from Task<T>
                var resultProperty = taskType.GetProperty("Result");
                if (resultProperty != null)
                {
                    return resultProperty.GetValue(task);
                }
            }
            
            // Non-generic Task - no result
            return null;
        }

        // Handle ValueTask<T>
        var type = result.GetType();
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTask<>))
        {
            // Convert ValueTask<T> to Task<T> and get result
            var asTaskMethod = type.GetMethod("AsTask");
            if (asTaskMethod != null)
            {
                var taskResult = (Task)asTaskMethod.Invoke(result, null)!;
                taskResult.GetAwaiter().GetResult();
                
                var resultProperty = taskResult.GetType().GetProperty("Result");
                return resultProperty?.GetValue(taskResult);
            }
        }

        // Handle non-generic ValueTask
        if (result is ValueTask valueTask)
        {
            valueTask.AsTask().GetAwaiter().GetResult();
            return null;
        }

        // Not a Task - return directly
        return result;
    }
}