namespace Indotalent.ConfigBackEnd.Extensions;

using Indotalent.Data.Interfaces;
using Indotalent.Shared.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

public static class IQueryableExtensions
{
    public static IQueryable<T> WhereIf<T>(
        this IQueryable<T> query,
        bool condition,
        Expression<Func<T, bool>> predicate)
    {
        return condition ? query.Where(predicate) : query;
    }

    public static async Task<PagedList<T>> ToPagedListAsync<T>(
            this IQueryable<T> query,
            int skip,
            int top)
    {
        top = top <= 0 ? 5 : top;
        skip = skip < 0 ? 0 : skip;

        var count = await query.CountAsync();

        var items = await query
            .Skip(skip)
            .Take(top)
            .ToListAsync();

        return new PagedList<T>(items, count, skip, top);
    }

    public static IQueryable<T> OrderByPropertyName<T>(
        this IQueryable<T> query,
        string? propertyName,
        bool isDescending)
    {
        if (string.IsNullOrWhiteSpace(propertyName)) return query;

        var parameter = Expression.Parameter(typeof(T), "x");
        var property = Expression.Property(parameter, propertyName);
        var lambda = Expression.Lambda(property, parameter);

        var methodName = isDescending ? "OrderByDescending" : "OrderBy";
        var resultExpression = Expression.Call(
            typeof(Queryable),
            methodName,
            new Type[] { typeof(T), property.Type },
            query.Expression,
            Expression.Quote(lambda));

        return query.Provider.CreateQuery<T>(resultExpression);
    }

    public static IQueryable<T> NotDeletedOnly<T>(this IQueryable<T> query)
        where T : class, IHasIsDeleted
    {
        return query.Where(x => !x.IsDeleted);
    }
}