using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Encryption;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System.Text;

namespace IRaCIS.Core.Application.BusinessFilter;

public class EncryptionRequestMiddleware
{
    private readonly RequestDelegate _next;

    private readonly IRCEncreptOption _IRCEncreptOption;

    public EncryptionRequestMiddleware(RequestDelegate next, IOptionsMonitor<IRCEncreptOption> encreptResponseMonitor)
    {
        _next = next;

        _IRCEncreptOption = encreptResponseMonitor.CurrentValue;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        //模拟前端已经设置该请求头
        //context.Request.Headers["X-Encrypted-Key"] = "hW8JuJocBzIPWSHURUnYJMZ0l68g6uP9rEdMho8ioFO8amD6GIH+R6RIX5jVFzOwO+lmgBi+4gaVJGGkWJMTcoDTfzzzT1EmfPV+UhFLE9HWvCkEXmDOLE9xCHrbG8TrR1I9+Qd3cvo9HLmrQ58n13cJsM82FBw+reUgiWeklPCkEWM9br2qc9VkCp6gKzimTldNTWBezV86S6j3qHbZpVZm0atdDtGb+zSC9LLA3+oHQwRLJAAGSOAi8CUiRmIQsygRd824wBndkaH2ImEeRjBMs7PqCeK3KsoDp13yHdj2AE751gsfNzf4SF547UPf72m0F2/rBFgrSNy+Jz0T9w==";

        // 检查请求头中是否包含加密的对称密钥
        if (context.Request.Headers.ContainsKey("X-Encrypted-Key"))
        {

            var encryptedSymmetricKeyStr = context.Request.Headers["X-Encrypted-Key"].ToString();

            var pemSecretKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.Base64RSAPrivateKey));

            // 使用私钥解密对称密钥
            var decryptedSymmetricKey = RSAEncryption.Decrypt(pemSecretKey, encryptedSymmetricKeyStr);


            #region 处理路径传递参数

            // 处理路径参数解密
            var path = context.Request.Path.Value;

            // 假设加密的参数在路径中，按照顺序解密路径中的每个部分
            var pathSegments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
            for (int i = 2; i < pathSegments.Length; i++)
            {
                if (!string.IsNullOrEmpty(pathSegments[i]))
                {
                    try
                    {
                        var decryptedSegment = AesEncryption.Decrypt(pathSegments[i], decryptedSymmetricKey);
                        pathSegments[i] = decryptedSegment;
                    }
                    catch
                    {
                        // 如果不能解密该部分，保持原值
                    }
                }
            }

            // 将解密后的路径重新拼接并设置到请求的Path
            context.Request.Path = "/" + string.Join("/", pathSegments);

            #endregion

            #region 处理url 传递参数

            // 处理 URL 查询参数的解密
            var queryParams = context.Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString());
            var decryptedQueryParams = new Dictionary<string, string>();

            foreach (var param in queryParams)
            {
                var encryptedValue = param.Value;
                var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
                decryptedQueryParams[param.Key] = decryptedValue;
            }

            // 构造解密后的查询字符串
            var decryptedQueryString = new QueryString("?" + string.Join("&", decryptedQueryParams.Select(kvp => $"{kvp.Key}={kvp.Value}")));
            context.Request.QueryString = decryptedQueryString;

            #endregion

            #region 处理body传参

            // 读取并解密请求体中的JSON数据
            context.Request.EnableBuffering();
            using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: true))
            {
                var encryptedBody = await reader.ReadToEndAsync();
                context.Request.Body.Position = 0;


                if (!string.IsNullOrEmpty(encryptedBody))
                {
                    // 尝试解析为JObject
                    var encryptedJson = JObject.Parse(encryptedBody);
                    var decryptedJson = new JObject();

                    // 解密每个字段的值
                    foreach (var property in encryptedJson.Properties())
                    {
                        var encryptedValue = property.Value.ToString();
                        var decryptedValue = AesEncryption.Decrypt(encryptedValue, decryptedSymmetricKey);
                        decryptedJson[property.Name] = decryptedValue;
                    }

                    // 将解密后的JSON对象转换回字符串，并替换原始请求体
                    var decryptedBody = decryptedJson.ToString();
                    var bodyStream = new MemoryStream(Encoding.UTF8.GetBytes(decryptedBody));
                    context.Request.Body = bodyStream;
                    context.Request.ContentLength = bodyStream.Length;
                    bodyStream.Seek(0, SeekOrigin.Begin);
                }
            }

            #endregion



        }
        // 调用下一个中间件
        await _next(context);
    }


}
