using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ReZero.SuperAPI 
{
    public partial class BindHttpParameters
    {
        internal void Bind(DataModel? dataModel, HttpContext context, string? path, bool isUrlParameters, ZeroInterfaceList interInfo)
        {
            var formDatas = GetFormDatas(context);
            BindPageParameters(dataModel, context, formDatas);
            BindDefaultParameters(dataModel, context, formDatas, interInfo);
            BindOrderByParameters(dataModel, context, formDatas);
            BindGroupByParameters(dataModel, context, formDatas);
            BindUrlParameters(isUrlParameters,path, dataModel!, interInfo);
        }

        private void BindUrlParameters(bool isUrlParameters, string? path, DataModel dataModel, ZeroInterfaceList interInfo)
        {
            if (isUrlParameters) 
            {
                var parameterString = path!.Replace(interInfo.OriginalUrl!.ToLower(), string.Empty);
                var parameters= parameterString.Split('/').Where(it=>!string.IsNullOrWhiteSpace(it)).ToArray();
                var index = 0;
                foreach (var item in dataModel.DefaultParameters??new List<DataModelDefaultParameter>())
                {
                    item.Value= parameters[index];
                    index++;
                }
            }
        }

        private void BindGroupByParameters(DataModel? dataModel, HttpContext context, Dictionary<string, object> formDatas)
        {
            if (dataModel?.GroupParemters != null)
            {
                var groupBys = formDatas.FirstOrDefault(it => it.Key.EqualsCase(nameof(DataModel.GroupParemters)));
                if (groupBys.Value != null)
                {
                    dataModel!.GroupParemters = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DataModelGroupParameter>>(groupBys.Value + "");
                }
            }
        }

        private void BindOrderByParameters(DataModel? dataModel, HttpContext context, Dictionary<string, object> formDatas)
        {
            if (dataModel?.OrderDynamicParemters != null)
            {
                //var data = dataModel?.DefaultParameters?.FirstOrDefault(it => it?.Name?.EqualsCase(nameof(DataModel.OrderByFixedParemters )) == true);
                //if (data != null)
                //{
                var orderDatas = formDatas.FirstOrDefault(it => it.Key.EqualsCase(nameof(DataModel.OrderDynamicParemters)));
                if (orderDatas.Value != null)
                {
                    dataModel!.OrderDynamicParemters = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DataModelDynamicOrderParemter>>(orderDatas.Value + "");
                }
                //}
            }
        }
        private void BindPageParameters(DataModel? dataModel, HttpContext context, Dictionary<string, object> formDatas)
        {
            if (dataModel?.CommonPage != null)
            {
                var pageNumberPar = dataModel?.DefaultParameters?.FirstOrDefault(it => it?.Name?.EqualsCase(SuperAPIModule._apiOptions?.InterfaceOptions.PageNumberPropName) == true);
                if (pageNumberPar != null)
                {
                    pageNumberPar.Value = GetParameterValueFromRequest(pageNumberPar, context, formDatas);
                    dataModel!.CommonPage.PageNumber = Convert.ToInt32(pageNumberPar.Value ?? "1");
                }
                var pageSizePar = dataModel?.DefaultParameters?.FirstOrDefault(it => it?.Name?.EqualsCase(SuperAPIModule._apiOptions?.InterfaceOptions.PageSizePropName) == true);
                if (pageSizePar != null)
                {
                    pageSizePar.Value = GetParameterValueFromRequest(pageSizePar, context, formDatas);
                    dataModel!.CommonPage.PageSize = Convert.ToInt32(pageSizePar.Value ?? "20");
                }
            }
        }

        private void BindDefaultParameters(DataModel? dataModel, HttpContext context, Dictionary<string, object> formDatas, ZeroInterfaceList interInfo)
        {
            if (IsJObjct(dataModel, formDatas))
            {
                var data = dataModel?.DefaultParameters?.FirstOrDefault();
                if (data != null)
                {
                    System.Diagnostics.Debug.WriteLine("检测到JObject请求参数,开始处理");
                    try
                    {
                        // 先检查是否有_rawJson
                        if (formDatas.ContainsKey("_rawJson"))
                        {
                            string rawJson = formDatas["_rawJson"].ToString();
                            System.Diagnostics.Debug.WriteLine($"使用_rawJson作为JObject参数: {rawJson}");
                            data.Value = rawJson;
                            
                            // 特殊处理登录接口:如果是token接口,则需要额外处理参数
                            if (interInfo.Url == "/api/rezero/token" && dataModel.DefaultParameters.Count == 2)
                            {
                                try
                                {
                                    // 解析原始JSON以获取登录凭证
                                    var loginParams = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(rawJson);
                                    if (loginParams != null)
                                    {
                                        // 将用户名和密码分别赋值给对应参数
                                        var userNameParam = dataModel.DefaultParameters.FirstOrDefault(p => p.Name?.EqualsCase("UserName") == true);
                                        var passwordParam = dataModel.DefaultParameters.FirstOrDefault(p => p.Name?.EqualsCase("Password") == true);
                                        
                                        if (userNameParam != null && loginParams.ContainsKey("UserName"))
                                        {
                                            userNameParam.Value = loginParams["UserName"];
                                        }
                                        else if (userNameParam != null && loginParams.ContainsKey("userName"))
                                        {
                                            userNameParam.Value = loginParams["userName"];
                                        }
                                        
                                        if (passwordParam != null && loginParams.ContainsKey("Password"))
                                        {
                                            passwordParam.Value = loginParams["Password"];
                                        }
                                        else if (passwordParam != null && loginParams.ContainsKey("password"))
                                        {
                                            passwordParam.Value = loginParams["password"];
                                        }
                                        
                                        System.Diagnostics.Debug.WriteLine($"登录参数已解析: UserName={userNameParam?.Value}, Password={(passwordParam?.Value != null ? "********" : "null")}");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine($"解析登录参数异常: {ex.Message}");
                                }
                            }
                            
                            return;  // 已找到JSON数据,提前返回
                        }
                        
                        // 读取请求body
                        context.Request.EnableBuffering();
                        context.Request.Body.Position = 0;
                        using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true))
                        {
                            var body = reader.ReadToEndAsync().Result;
                            if (!string.IsNullOrEmpty(body))
                            {
                                data.Value = body;
                                System.Diagnostics.Debug.WriteLine($"JObject参数值设置为: {body}");
                            }
                            else if (formDatas.ContainsKey("methodName") && formDatas.ContainsKey("data"))
                            {
                                // 尝试构建符合接口要求的JSON对象
                                var jsonObj = new
                                {
                                    methodName = formDatas["methodName"],
                                    data = formDatas["data"]
                                };
                                data.Value = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj);
                                System.Diagnostics.Debug.WriteLine($"从formDatas构建JObject参数: {data.Value}");
                            }
                            else
                            {
                                data.Value = Newtonsoft.Json.JsonConvert.SerializeObject(formDatas);
                                System.Diagnostics.Debug.WriteLine($"使用formDatas序列化作为JObject参数: {data.Value}");
                            }
                        }
                        context.Request.Body.Position = 0;
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"处理JObject参数异常: {ex.Message}");
                        data.Value = Newtonsoft.Json.JsonConvert.SerializeObject(formDatas);
                    }
                }
            }
            else if (dataModel!.DefaultParameters != null)
            {
                if (interInfo.IsAttributeMethod==true)
                {
                    //
                }
                else
                {
                    dataModel!.DefaultParameters = dataModel?.DefaultParameters?.Where(it => NoPageParameters(it)).ToList();
                }
                foreach (var item in dataModel?.DefaultParameters ?? new List<DataModelDefaultParameter>())
                {
                    UpdateWhereItemValue(context, formDatas, item);
                }
            }
        }

        private static bool IsJObjct(DataModel? dataModel, Dictionary<string, object> formDatas)
        {
            if (dataModel?.DefaultParameters == null || !dataModel.DefaultParameters.Any())
                return false;
            
            var firstParam = dataModel.DefaultParameters.First();
            
            // 检查是否是JToken或其子类型
            bool isJTokenType = firstParam.ValueType == nameof(JObject) || 
                               firstParam.ValueType == nameof(JToken) || 
                               firstParam.ValueType == "JTokenType" ||
                               firstParam.ValueType == "Json" || 
                               (firstParam.ValueType?.Contains("JToken") == true) ||
                               (firstParam.ValueType?.Contains("JObject") == true);
            
            bool isSingleParam = dataModel.DefaultParameters.Count == 1;
            
            // 检查bodyJson
            bool hasJsonBody = formDatas.ContainsKey("_rawJson");
            
            var isJObject = (isSingleParam && isJTokenType) || hasJsonBody;
            
            System.Diagnostics.Debug.WriteLine($"IsJObjct检查: {isJObject}, 参数类型: {firstParam.ValueType}, 有原始JSON: {hasJsonBody}, MethodArgs: {dataModel?.MyMethodInfo?.MethodArgsCount}");
            
            return isJObject;
        }

        private void UpdateWhereItemValue(HttpContext context, Dictionary<string, object> formDatas, DataModelDefaultParameter item)
        {
            item.Value = GetParameterValueFromRequest(item, context, formDatas);
            if (IsDefaultValue(item))
            {
                item.Value = item.DefaultValue;
            }
            if (IsUserName(item))
            {
                var options = SuperAPIModule._apiOptions;
                item.Value = options?.DatabaseOptions!.GetCurrentUserCallback().UserName;
            }
            else if (IsDateTimeNow(item))
            {
                var options = SuperAPIModule._apiOptions;
                item.Value = DateTime.Now;
            }
            else if (IsFile(item))
            {
                item.Value = PubMethod.ConvertFromBase64(item.Value + "");
            }
            //if (!string.IsNullOrEmpty(item?.FieldName))
            //{
            //    item.Name = item.FieldName;
            //}
        }



        private static bool NoPageParameters(DataModelDefaultParameter it)
        {
            return it.Name != SuperAPIModule._apiOptions?.InterfaceOptions.PageNumberPropName &&
                        it.Name != SuperAPIModule._apiOptions?.InterfaceOptions.PageSizePropName;
        }

        private static bool IsUserName(DataModelDefaultParameter item)
        {
            return item?.InsertParameter?.IsUserName == true;
        }
        private static bool IsDateTimeNow(DataModelDefaultParameter item)
        {
            return item?.InsertParameter?.IsDateTimeNow == true;
        }
        private bool IsFile(DataModelDefaultParameter item)
        {
            return item?.ValueType == "Byte[]";
        }
        private static bool IsDefaultValue(DataModelDefaultParameter item)
        {
            return item.Value == null && item.DefaultValue != null;
        }

        private string GetParameterValueFromRequest(DataModelDefaultParameter parameter, HttpContext context, Dictionary<string, object> formDatas)
        {
            if (parameter.ValueIsReadOnly)
            {
                return parameter.Value + "";
            }
            string parameterValue = context.Request.Query[parameter.Name];
            var formData = formDatas.FirstOrDefault(it => it.Key.EqualsCase(parameter.Name ?? ""));
            if (formData.Key == null)
            {
                // 尝试使用不区分大小写的方式查找
                formData = formDatas.FirstOrDefault(it => string.Equals(it.Key, parameter.Name, StringComparison.OrdinalIgnoreCase));
            }
            if (formData.Key != null)
            {
                parameterValue = formData.Value + "";
            }
            parameter.Value = parameterValue;
            return parameterValue;
        }

        private static Dictionary<string, object> GetFormDatas(HttpContext context)
        {

            Dictionary<string, object> formDatas = new Dictionary<string, object>();
            if (context.Request.Body != null)
            {
                AddFormData(context, formDatas);
                AddRawParameters(context, formDatas);
            }
            return formDatas ?? new Dictionary<string, object>();
        }

        private static void AddFormData(HttpContext context, Dictionary<string, object> formDatas)
        {
            if (IsFormData(context))
            {
                var formParams = context.Request.Form;

                foreach (var key in formParams.Keys)
                {
                    formDatas[key] = formParams[key];
                }
            }
        }

        private static void AddRawParameters(HttpContext context, Dictionary<string, object> formDatas)
        {
            try
            {
                context.Request.EnableBuffering();
                context.Request.Body.Position = 0;
                
                string body;
                using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true))
                {
                    body = reader.ReadToEndAsync().Result;
                }
                
                context.Request.Body.Position = 0;
                
                if (!string.IsNullOrEmpty(body))
                {
                    System.Diagnostics.Debug.WriteLine($"原始请求体: {body}");
                    
                    // 检查是否是有效的JSON格式
                    if ((body.StartsWith("{") && body.EndsWith("}")) || 
                        (body.StartsWith("[") && body.EndsWith("]")))
                    {
                        // 保存原始JSON,仅当不需要将其解析为字典时使用
                        formDatas["_rawJson"] = body;
                        
                        // 检查请求头,如果是 application/json,并且第一个参数是预期为JObject类型,
                        // 则不要解析为字典,避免重复处理,以防止在BindDefaultParameters中的JObject处理逻辑冲突
                        var contentType = context.Request.ContentType?.ToLower() ?? "";
                        if (contentType.Contains("application/json"))
                        {
                            // 在JObject处理中,我们会直接使用_rawJson,所以这里不需要解析为字典
                            // 仅保存原始JSON足够了
                            System.Diagnostics.Debug.WriteLine("检测到JSON内容类型,保留原始JSON供JObject处理");
                            return;
                        }
                        
                        try
                        {
                            var bodyParams = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(body);
                            
                            if (bodyParams != null)
                            {
                                foreach (var item in bodyParams)
                                {
                                    if (!formDatas.ContainsKey(item.Key))
                                    {
                                        formDatas[item.Key] = item.Value;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine($"解析请求体异常: {ex.Message}");
                            // 如果解析为字典失败,原始JSON已保存
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"处理请求体异常: {ex.Message}");
            }
        }

        private static bool IsFormData(HttpContext context)
        {
            var contentTypes = new List<string>()
            {
                "multipart/form-data",
                "application/x-www-form-urlencoded"
            };
            return context.Request.ContentType != null && contentTypes.Any(context.Request.ContentType.Contains);
        }
    }
}