using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using XYY.Common.Standard;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;

namespace XYY.Core.Standard.Mvc
{
    public class QueryModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Metadata.ModelType == typeof(QueryModel))
            {
                return new BinderTypeModelBinder(typeof(QueryModelBinder));
            }

            return null;
        }
    }

    public class QueryModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var body = bindingContext.HttpContext.Request.Body;
            byte[] b = new byte[bindingContext.HttpContext.Request.ContentLength ?? 0];
            body.Read(b, 0, b.Length);

            string str = System.Text.Encoding.Default.GetString(b);


            var valueProvider = bindingContext.ValueProvider;
            var modelName = bindingContext.ModelName;

            var valueProviderResult = valueProvider.GetValue(modelName);

            if (valueProviderResult == ValueProviderResult.None)
            {
                return Task.CompletedTask;
            }
            string sortField = bindingContext.ActionContext.HttpContext.Request.Query["sort"];
            string sortDirection = bindingContext.ActionContext.HttpContext.Request.Query["order"];
            var dict = bindingContext.HttpContext.Request.Query;
            var keys = dict.Where(c => c.Key.StartsWith("_"));//只有"["开头的为需要处理的

            List<QueryParamer> queryParamer = new List<QueryParamer>();
            if (keys.Count() != 0)
            {
                foreach (var key in keys)
                {
                    if (!key.Key.StartsWith("_")) continue;
                    var val = key.Value;
                    //处理无值的情况
                    if (string.IsNullOrEmpty(val)) continue;
                    //if (val.ToLower().Contains("wp-"))
                    //{
                    //    val = val.ToLower().Replace("wp-", "").TryConvertInt32().ToString();
                    //} 

                    var paramer = AddParamer(key.Key, val);
                    if (paramer != null)
                    {
                        queryParamer.Add(paramer);
                    }

                }
            }

            if (!int.TryParse(bindingContext.ActionContext.HttpContext.Request.Query["limit"], out int pageSize))
                pageSize = 20;
            if (!int.TryParse(bindingContext.ActionContext.HttpContext.Request.Query["offset"], out int pageIndex))
                pageIndex = 1;

            List<QuerySort> sort = new List<QuerySort>();
            if (!string.IsNullOrWhiteSpace(sortField))
                sort.Add(new QuerySort() { Field = sortField, IsDesc = (sortDirection == "desc") });
            var m = new QueryModel()
            {
                PageSize = pageSize,
                PageIndex = pageIndex / pageSize + 1,
                QuerySort = sort,
                QueryParamer = queryParamer
            };
            bindingContext.Result = ModelBindingResult.Success(m);
            return Task.CompletedTask;
        }


        private QueryParamer AddParamer(string item, string value)
        {
            string[] strArr = item.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
            if (strArr.Length != 2)
                return null;
            string method = "", field = "";
            method = strArr[0];
            field = strArr[1];

            string decVal = HttpUtility.UrlDecode(value, Encoding.UTF8);

            //html datetime-local的时间格式
            if (Regex.Match(decVal, @"\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}").Success && DateTime.TryParse(decVal, out var dateTime))
            {
                decVal = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
            }
            return new QueryParamer()
            {
                Filed = field.Replace("[", "").Replace("]", ""),
                Value = decVal,
                Method = method
            };

        }
    }
}
