using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CloudGaming.Code.MiddlewareExtend;

/// <summary>
/// 参数请求加密验证
/// </summary>
public class SignMiddleware
{

    private readonly RequestDelegate _next;
    public SignMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, AppConfig appConfig)
    { // 读取请求体
        context.Request.EnableBuffering();
        if (context.Request.Method != "POST" || context.Request.Host.Host == "localhost" || context.Request.Host.Host == "192.168.1.23")
        {
            // 调用下一个中间件
            await _next(context);
            return;
        }

        // 启用请求流的多次读取功能
        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))
        {
            var response = GetSignError(context);
            context.Response.ContentType = "application/json; charset=utf-8";
            await context.Response.WriteAsync(response);
            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) + appConfig.TenantId.ToString("N");

        // 计算 MD5 哈希值
        var md5Hash = MD5Encryption.ComputeMD5Hash(concatenatedValues).ToLower();
        // 验证 MD5 哈希值与请求中的 sign 是否匹配
        if (md5Hash != requestSign.ToLower())
        {
            var response = GetSignError(context);
            context.Response.ContentType = "application/json; charset=utf-8";
            context.Response.Headers["X-Request-Sign-Value"] = concatenatedValues;
            context.Response.Headers["X-Request-Sign"] = md5Hash;
            // 将异常信息写入 HTTP 响应
            await context.Response.WriteAsync(response);
            //await context.Response.WriteAsync("");
            return;
        }

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

    private static string GetSignError(HttpContext context)
    {

        // 返回 500 错误
        context.Response.StatusCode = 200;
        BaseResponse<object> baseResponse = new BaseResponse<object>(ResponseCode.SignError, "sign加密验证失败", null)
        { };
        var json = baseResponse.ToString();
        return json;
    }
}
