using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;

namespace IRaCIS.Core.Infrastructure.Extention
{
    public static class QueryablePageListExtensions
    {
        //单字段排序
        public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
        {
            if (pageIndex <= 0)
            {
                pageIndex = 1;
            }
            if (pageSize <= 0)
            {
                pageSize = 10;
            }
            var count = source.Count();

            if (count == 0)
            {
                return new PageOutput<T>() { CurrentPageData=new T[0] };
            }


            var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;

            source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");

            source = source.Skip((pageIndex - 1) * pageSize);

            var items = source
                                    .Take(pageSize)
                                    .ToArray();

            var pagedList = new PageOutput<T>()
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                TotalCount = count,
                CurrentPageData = items
            };

            return pagedList;
        }

        //单字段排序 异步
        public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true,bool isMultiSortFiled=false, string[] sortArray=default, CancellationToken cancellationToken = default)
        {

            if (isMultiSortFiled&& sortArray==default)
            {
                throw new System.Exception("必须指定排序字段");
            }

            if (pageNumber <= 0)
            {
                pageNumber = 1;
            }
            if (pageSize <= 0)
            {
                pageSize = 10;
            }

            var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);

            if (count == 0)
            {
                return new PageOutput<T>() { CurrentPageData = new T[0] };
            }
            var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;

            if (!isMultiSortFiled)
            {
                source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");

            }
            else
            {
                var sortString = string.Join(',', sortArray);

                source= source.OrderBy(sortString);
            }
            source = source.Skip((pageNumber - 1) * pageSize);
            var items = await source
                                    .Take(pageSize)
                                    .ToArrayAsync(cancellationToken)
                                    .ConfigureAwait(false);

            var pagedList = new PageOutput<T>()
            {
                PageIndex = pageNumber,
                PageSize = pageSize,
                TotalCount = count,
                CurrentPageData = items
            };

            return pagedList;
        }

        //多字段排序 ["a asc", "b desc", "c asc"]
        public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize,string[] sortArray)
        {
            if (pageIndex <= 0)
            {
                pageIndex = 1;
            }
            if (pageSize <= 0)
            {
                pageSize = 10;
            }
            var count = source.Count();

            if (count == 0)
            {
                return new PageOutput<T>() { CurrentPageData = new T[0] };
            }

            var sortString = string.Join(',', sortArray);

            source.OrderBy(sortString);

            source = source.Skip((pageIndex - 1) * pageSize);

            var items = source
                                    .Take(pageSize)
                                    .ToArray();

            var pagedList = new PageOutput<T>()
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                TotalCount = count,
                CurrentPageData = items
            };

            return pagedList;
        }

        //多字段排序异步 ["a asc", "b desc", "c asc"]
        public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string[] sortArray, CancellationToken cancellationToken = default)
        {
            if (pageNumber <= 0)
            {
                pageNumber = 1;
            }
            if (pageSize <= 0)
            {
                pageSize = 10;
            }

            var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);

            if (count == 0)
            {
                return new PageOutput<T>() { CurrentPageData = new T[0] };
            }

            var sortString = string.Join(',', sortArray);

            source = source.OrderBy(sortString);

            source = source.Skip((pageNumber - 1) * pageSize);
            var items = await source
                                    .Take(pageSize)
                                    .ToArrayAsync(cancellationToken)
                                    .ConfigureAwait(false);

            var pagedList = new PageOutput<T>()
            {
                PageIndex = pageNumber,
                PageSize = pageSize,
                TotalCount = count,
                CurrentPageData = items
            };

            return pagedList;
        }
    }
}
