using System.Linq.Expressions;
using System.Reflection;

namespace Lada.Framework.DTO.SmartTable
{
    public static class OrderByExtension
    {
        public static IQueryable<T> OrderByName<T>(this IQueryable<T> source, string propertyName, bool isDescending)
        {
            if (source == null)
            {
                throw new ArgumentException("source");
            }

            if (string.IsNullOrWhiteSpace(propertyName))
            {
                throw new ArgumentException("propertyName");
            }

            Type type = typeof(T);
            ParameterExpression arg = Expression.Parameter(type, "x");

            // Hỗ trợ nested property path (e.g. "OrderOps.DisplayOrder")
            Expression expression = arg;
            var propertyNames = propertyName.Split('.');
            foreach (var propName in propertyNames)
            {
                PropertyInfo propertyInfo = expression.Type.GetProperty(propName);
                if (propertyInfo == null)
                {
                    throw new ArgumentException($"Property '{propName}' not found on type '{expression.Type.Name}'");
                }
                expression = Expression.Property(expression, propertyInfo);
            }
            type = expression.Type;

            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expression, arg);

            var methodName = isDescending ? "OrderByDescending" : "OrderBy";
            object result = typeof(Queryable).GetMethods().Single(
                    method => method.Name == methodName
                              && method.IsGenericMethodDefinition
                              && method.GetGenericArguments().Length == 2
                              && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), type)
                .Invoke(null, new object[] { source, lambda });
            return (IQueryable<T>)result;
        }
    }
}
