//using Modules.Library.Domain.Entities;
//using System.Linq.Expressions;
//using System.Reflection;

//namespace Modules.Library.Domain.Utils;

//internal class Order_(IEnumerable<IOrderableItem> orderableItems)
//{
//    //internal void SetItemOrder(ushort old, ushort @new)
//    /*
//    internal void SetItemOrder(ushort lastOrder, ushort newOrder)
//    {
//        if (newOrder < 0 || newOrder > orderableItems.Select(q => q.Order).DefaultIfEmpty<ushort>(0).Max())
//            throw new ArgumentOutOfRangeException(nameof(newOrder));
//        //if (lastOrder == newOrder) return;
//        var newOrderItem = orderableItems.First(q => q.Order == newOrder);
//        orderableItems.First(q => q.Order == lastOrder).Order = newOrder;
//        foreach (var item in orderableItems.Where(q => q.Order > Math.Min(lastOrder, newOrder) && q.Order < Math.Max(lastOrder, newOrder)))
//        {
//            if (lastOrder > newOrder) item.Order++;
//            else if (lastOrder < newOrder) item.Order--;
//        }
//        if (lastOrder > newOrder) newOrderItem.Order++;
//        else if (lastOrder < newOrder) newOrderItem.Order--;
//    }
    
//    internal void SetItemOrder(ushort lastOrder, ushort newOrder)
//    {
//        if (newOrder < 0 || newOrder > orderableItems.Select(q => q.Order).DefaultIfEmpty<ushort>(0).Max())
//            throw new ArgumentOutOfRangeException(nameof(newOrder));
//        //if (lastOrder == newOrder) return;
//        var newOrderItem = orderableItems.First(q => q.Order == newOrder);
//        orderableItems.First(q => q.Order == lastOrder).Order = newOrder;
//        foreach (var item in orderableItems.Where(q => q.Order > Math.Min(lastOrder, newOrder) && q.Order < Math.Max(lastOrder, newOrder)))
//        {
//            if (lastOrder > newOrder) item.Order++;
//            else if (lastOrder < newOrder) item.Order--;
//        }
//        if (lastOrder > newOrder) newOrderItem.Order++;
//        else if (lastOrder < newOrder) newOrderItem.Order--;
//    }
    
//    */

//    private static Expression SetItemOrder(ushort lastOrder, ushort newOrder)
//    {
//        var parameterItemsEx = Expression.Parameter(typeof(List<IOrderableItem>));
//        /*
//        var propertyItemsOrderEx = Expression.Property(parameterItemsEx,
//            typeof(IEnumerable<IOrderableItem>).GetProperty(nameof(IOrderableItem.Order))!.GetGetMethod()!);
//        */
//        var parameterOldOrderEx = Expression.Parameter(typeof(ushort));
//        var parameterNewOrderEx = Expression.Parameter(typeof(ushort));

        
//        Func<List<IOrderableItem>, ushort, IOrderableItem> getItemByOrder = (items, order) => items.First(q => q.Order == order);
//        var getNewOrderItemEx = Expression.Invoke(Expression.Constant(getItemByOrder), [parameterItemsEx, parameterNewOrderEx]);
        

//        var itemVariableEx = Expression.Variable(typeof(IOrderableItem));
//        var orderVariableEx = Expression.Variable(typeof(ushort));

//        Action<IOrderableItem, ushort> setItemOrder = (item, order) => item.SetPropertyValue(c => c.Order, order);
//        var setItemOrderEx = Expression.Invoke(Expression.Constant(setItemOrder), [itemVariableEx, orderVariableEx]);

//        var iteratorEx = Expression.Variable(typeof(int));
//        var iteratorSetZeroEx = Expression.Assign(iteratorEx, Expression.Constant(0));

//        Func<List<IOrderableItem>, int, IOrderableItem> getItemFunc = (list, i) => list[i];
//        var getItemEx = Expression.Invoke(Expression.Constant(getItemFunc), [parameterItemsEx, iteratorEx]);
        

//        Func<List<IOrderableItem>, int> itemsCountFunc = q => q.Count;
//        var itemsCountEx = Expression.Invoke(Expression.Constant(itemsCountFunc), [parameterItemsEx]);

//        LoopExpression loop = Expression.Loop(
//            Expression.IfThenElse(
//                // test
//                Expression.LessThan(iteratorEx, itemsCountEx),
//                // if true
//                Expression.Block(
//                [
//                    Expression.Condition()
//                    Expression.Increment(iteratorEx),
//                ]
//                ),

//               // if false
//               Expression.Break(loopBreakLabel)
//               ), loopBreakLabel);

//        return Expression.Block(
//            new[] { enumeratorVar, classElementVar },

//            // get enumerator from class collection
//            Expression.Assign(enumeratorVar, getEnumeratorCall),

//            // loop over classes
//            loop);


//        orderableItems.First(q => q.Order == lastOrder).Order = newOrder;
//        var a = Expression.Lambda<IEnumerable<IOrderableItem>, ushort, bool>(IsOrderOutOfRange, [parameterItems, parameterNewOrder]);
//        var checkNewOrderCondition = Expression.IsTrue();


//        Func<IEnumerable<IOrderableItem>, ushort, bool> checkIfOrderOutOfRange = IsOrderOutOfRange;
//        var checkIfOldOrderOutOfRangeEx = Expression.Invoke(Expression.Constant(checkIfOrderOutOfRange), [parameterItemsEx, parameterOldOrderEx]);
//        var checkOldOrderCondition = Expression.Condition(Expression.IsFalse(checkIfOldOrderOutOfRangeEx), callNext, throw);



//        var checkIfNewOrderOutOfRangeEx = Expression.Invoke(Expression.Constant(checkIfOrderOutOfRange), [parameterItemsEx, parameterNewOrderEx]);
//        var checkNewOrderCondition = Expression.Condition(Expression.IsFalse(checkIfNewOrderOutOfRangeEx), checkOldOrderCondition, throw);


//        if (newOrder < 0 || newOrder > orderableItems.Select(q => q.Order).DefaultIfEmpty<ushort>(0).Max())
//            throw new ArgumentOutOfRangeException(nameof(newOrder));
//        //if (lastOrder == newOrder) return;
//        var newOrderItem = orderableItems.First(q => q.Order == newOrder);
//        orderableItems.First(q => q.Order == lastOrder).Order = newOrder;
//        foreach (var item in orderableItems.Where(q => q.Order > Math.Min(lastOrder, newOrder) && q.Order < Math.Max(lastOrder, newOrder)))
//        {
//            if (lastOrder > newOrder) item.Order++;
//            else if (lastOrder < newOrder) item.Order--;
//        }
//        if (lastOrder > newOrder) newOrderItem.Order++;
//        else if (lastOrder < newOrder) newOrderItem.Order--;

//    }
//    */
//    /*
//    internal static LambdaExpression UpdateOrderTo(IOrderableItem item, ushort order)
//    {
//        var orderItemParam = Expression.Parameter(typeof(IOrderableItem));
//        var orderParam = Expression.Parameter(typeof(ushort));

//        var destNewExpr = Expression.Assign(orderParam, Expression.Bind(typeof(IOrderableItem).GetProperty(nameof(IOrderableItem.Order))!, orderparam));
//        var memberbindings = new List<MemberBinding>();

//        IPerson_Name destName;
//        IPerson_Name srcName;
//        if ((tDest.IsInstanceOfType(typeof(IPerson_Name)) || tDest.IsInstanceOfType(typeof(Person))) &&
//            (tSrc.IsInstanceOfType(typeof(IPerson_Name)) || tSrc.IsInstanceOfType(typeof(Person))))
//        {
//            memberbindings.Add(Expression.Bind(tDest.GetProperty("Name"), Expression.Property(personparam, "Name")));
//        }

//        var toEntityParameterExpression = Expression.MemberInit(destNewExpr, memberbindings);

//        return Expression.Lambda(
//                toEntityParameterExpression,
//                personparam
//            );
//    }
//    */


//    private static bool IsOrderOutOfRange(IEnumerable<IOrderableItem> orderableItems, ushort order) => order < 0 ||
//        order > orderableItems.Select(q => q.Order).DefaultIfEmpty<ushort>(0).Max();
//}

//public static class LambdaExtensions
//{
//    public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T, TValue>> memberLamda, TValue value)
//    {
//        var memberSelectorExpression = memberLamda.Body as MemberExpression;
//        if (memberSelectorExpression != null)
//        {
//            var property = memberSelectorExpression.Member as PropertyInfo;
//            if (property != null)
//            {
//                property.SetValue(target, value, null);
//            }
//        }
//    }
//}
