using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json.Linq;
using HuanMeng.DotNetCore.Base;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace HuanMeng.DotNetCore.MiddlewareExtend
{
    /// <summary>
    /// 参数请求加密验证
    /// </summary>
    public class SignBaseMiddleware
    {
        private readonly RequestDelegate _next;
        private const string FixedString = "cccc"; // 固定字符串
        public SignBaseMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            // 读取请求体
            context.Request.EnableBuffering(); // 启用请求流的多次读取功能
            var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
            context.Request.Body.Position = 0; // 重置请求体的位置

            if (string.IsNullOrEmpty(requestBody))
            {
                await _next(context);
                return;
            }
            // 解析请求体为 JSON 对象
            var requestJson = JObject.Parse(requestBody);
            // 获取请求中的 sign 值
            var requestSign = requestJson["sign"]?.ToString();
            if (string.IsNullOrEmpty(requestSign))
            {
                await _next(context);
                return;
            }
            // 获取所有的键值对，并排序
            var sortedKeys = requestJson.Properties()
                                         .Where(p => p.Name != "sign")
                                         .OrderBy(p => p.Name)
                                         .Select(p => p.Value.ToString())
                                         .ToList();

            // 拼接所有的值，并加上固定字符串
            var concatenatedValues = string.Join("", sortedKeys) + FixedString;

            // 计算 MD5 哈希值
            var md5Hash = ComputeMD5Hash(concatenatedValues);



            // 验证 MD5 哈希值与请求中的 sign 是否匹配
            if (md5Hash != requestSign)
            {
                var settings = new JsonSerializerSettings
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };
                // 返回 500 错误
                context.Response.StatusCode = 500;
                BaseResponse<object> baseResponse = new BaseResponse<object>(ResponseCode.SignError, "sign加密验证失败", null)
                {

                };
                context.Response.ContentType = "application/json; charset=utf-8";
                // 将异常信息写入 HTTP 响应
                await context.Response.WriteAsync(JsonConvert.SerializeObject(baseResponse));
                //await context.Response.WriteAsync("");
                return;
            }

            // 调用下一个中间件
            await _next(context);
        }
        /// <summary>
        /// Md5加密
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private string ComputeMD5Hash(string input)
        {
            using (var md5 = MD5.Create())
            {
                var inputBytes = Encoding.UTF8.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
            }
        }
    }
}
