using Microsoft.AspNetCore.Http;

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

using System.Text;

namespace CloudGaming.Code.JY;

/// <summary>
/// JYAPI请求处理器
/// </summary>
public class JYApiHandler : DelegatingHandler
{
    protected readonly IHttpContextAccessor _httpContextAccessor;

    public JYApiHandler(IHttpContextAccessor? httpContextAccessor)
    {
        if (httpContextAccessor != null)
        {
            _httpContextAccessor = httpContextAccessor;
        }
    }

    /// <summary>
    /// 发送请求的核心处理方法
    /// </summary>
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            await SetRequest(request);
            var sw = Stopwatch.StartNew();
            var response = await base.SendAsync(request, cancellationToken);
            sw.Stop();
            if (response.IsSuccessStatusCode)
            {
                await AttachDebugInfoAsync(request, response, sw.Elapsed.TotalMilliseconds.ToString());
            }
            return response;
        }
        catch (Exception ex)
        {
            // 可根据实际需要扩展异常处理逻辑
            throw new HttpRequestException("发送请求时发生错误。", ex);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    /// <exception cref="InvalidOperationException"></exception>
    protected virtual async Task SetRequest(HttpRequestMessage request)
    {
        var httpContext = _httpContextAccessor.HttpContext;
        if (httpContext == null)
            throw new InvalidOperationException("无法获取HttpContext。");

        var host = httpContext.Request.Host.Host;
        var app = AppConfigurationExtend.GetAppConfig(host);
        if (app != null)
        {
            UpdateRequestUri(request, app.GameConfig.BsUrl);

            if (request.Content is FormUrlEncodedContent)
            {

                await UpdateRequestContentAsync(request, app, httpContext.GetClientIpAddress());
            }
        }
    }

    /// <summary>
    /// 更新请求的URI
    /// </summary>
    protected void UpdateRequestUri(HttpRequestMessage request, string baseUrl)
    {
        var newUri = new Uri(new Uri(baseUrl), request.RequestUri.PathAndQuery);
        request.RequestUri = newUri;
    }

    /// <summary>
    /// 更新请求内容
    /// </summary>
    protected async Task UpdateRequestContentAsync(HttpRequestMessage request, AppConfig app, string ip)
    {
        var formData = await request.Content.ReadAsStringAsync();
        var parameters = ParseFormData(formData);

        AddDefaultParameters(parameters, app, ip);

        var signKey = GenerateSignature(parameters, app.GameConfig.SignKey);
        var encryptedParameters = $"{ConvertDictionaryToPostData(parameters)}&sign={signKey}";

        request.Content = new StringContent(encryptedParameters, Encoding.UTF8, "application/x-www-form-urlencoded");
    }

    /// <summary>
    /// 添加默认参数
    /// </summary>
    protected void AddDefaultParameters(SortedDictionary<string, object> parameters, AppConfig app, string ip)
    {
        if (!parameters.ContainsKey("channel_id"))
        {
            parameters["channel_id"] = app.GameConfig.ChannelId;
        }

        if (!parameters.ContainsKey("ip"))
        {
            parameters["ip"] = ip;
        }

        if (!parameters.ContainsKey("time"))
        {
            parameters["time"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        }
    }

    /// <summary>
    /// 生成签名
    /// </summary>
    protected string GenerateSignature(SortedDictionary<string, object> parameters, string signKey)
    {
        var dataString = string.Join("&", parameters.Select(kv => $"{kv.Key}={kv.Value}")) + $"&key={signKey}";
        return MD5Encryption.ComputeMD5Hash(dataString).ToUpper();
    }

    /// <summary>
    /// 附加调试信息到响应
    /// </summary>
    protected async Task AttachDebugInfoAsync(HttpRequestMessage request, HttpResponseMessage response, string totalMilliseconds)
    {
        var responseContent = await response.Content.ReadAsStringAsync();
        var responseJson = JsonConvert.DeserializeObject<JObject>(responseContent);

        responseJson["RequestStr"] = await request.ToJsonAsync();
        responseJson["ResponseStr"] = SerializeResponse(response, responseContent);
        responseJson["TotalMilliseconds"] = totalMilliseconds;
        responseJson["ResponseContent"] = responseContent;

        var newContent = new StringContent(JsonConvert.SerializeObject(responseJson), Encoding.UTF8, "application/json");
        response.Content = newContent;
    }

    /// <summary>
    /// 序列化HTTP响应
    /// </summary>
    protected string SerializeResponse(HttpResponseMessage response, string content)
    {
        return JsonConvert.SerializeObject(new
        {
            response.StatusCode,
            response.ReasonPhrase,
            Headers = response.Headers,
            Content = content
        });
    }
    /// <summary>
    /// 解析表单数据
    /// </summary>
    protected SortedDictionary<string, object> ParseFormData(string formData)
    {
        var parameters = new SortedDictionary<string, object>();
        var pairs = formData.Split('&');

        foreach (var pair in pairs)
        {
            var keyValue = pair.Split('=');
            if (keyValue.Length == 2)
            {
                parameters[keyValue[0]] = keyValue[1];
            }
        }
        return parameters;
    }


    /// <summary>
    /// 将字典转换为POST数据格式
    /// </summary>
    protected string ConvertDictionaryToPostData(SortedDictionary<string, object> dictionary)
    {
        return string.Join("&", dictionary.Select(kv => $"{kv.Key}={kv.Value}"));
    }
}
