using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Edu.Common.Pay.WeChatPat
{
    /// <summary>
    /// 微信支付响应类
    /// </summary>
    public class ResponseHandler
    {
        /// <summary>
        /// 密钥
        /// </summary>
        private string _key;

        /// <summary>
        /// 微信服务器编码方式
        /// </summary>
        private const string Charset = "utf-8";


        public Hashtable XmlMap { get; }

        /// <summary>
        /// 获取页面提交的参数
        /// </summary>
        /// <param name="_accessor"></param>
        public ResponseHandler(IHttpContextAccessor _accessor)
        {
            XmlMap = new Hashtable();
            #region 
            //注意：如果用以下读取流的方法，.net core 3.0 以后一定要加下边那段
            //.net core 3.0以后需加下边这段，否则Stream会报错
            var syncIOFeature = _accessor.HttpContext.Features.Get<IHttpBodyControlFeature>();
            if (syncIOFeature != null)
            {
                syncIOFeature.AllowSynchronousIO = true;
            }
            #endregion


            //接收从微信后台POST过来的数据
            System.IO.Stream s = _accessor.HttpContext.Request.Body;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            int count;
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();
            Plugin.LogHelper.WriteInfo($"GetNotifyData Receive data from WeChat :{builder.ToString()}");

            //转换数据格式并验证签名
           // WxPayData data = new WxPayData();
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(builder.ToString());
                XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
                XmlNodeList nodes = xmlNode.ChildNodes;
                foreach (XmlNode xn in nodes)
                {
                    XmlMap.Add(xn.Name, xn.InnerText);
                }
            }
            catch (Exception ex)
            {
                //若签名错误，则立即返回结果给微信支付后台
                Common.Plugin.LogHelper.Write(ex, "ResponseHandler");
            }
            Plugin.LogHelper.WriteInfo($"GetNotifyData Check sign success");
        }

        /// <summary>
        /// 初始化加载
        /// </summary>
        public virtual void Init()
        {
        }

        /// <summary>
        /// 获取密钥
        /// </summary>
        /// <returns></returns>
        public string GetKey()
        {
            return _key;
        }

        /// <summary>
        /// 设置密钥
        /// </summary>
        /// <param name="key"></param>
        public void SetKey(string key)
        {
            this._key = key;
        }

        /// <summary>
        /// 获取参数值
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public string GetParameter(string parameter)
        {
            var s = (string)XmlMap[parameter];
            return s ?? "";
        }

        /// <summary>
        /// 判断微信签名
        /// </summary>
        /// <returns></returns>
        public virtual bool IsWXsign(out string error)
        {
            var sb = new StringBuilder();
            var signMap = new Hashtable();
            foreach (string k in XmlMap.Keys)
            {
                if (k != "sign")
                {
                    signMap.Add(k.ToLower(), XmlMap[k]);
                }
            }
            var akeys = new ArrayList(signMap.Keys);
            akeys.Sort();
            foreach (string k in akeys)
            {
                var v = (string)signMap[k];
                sb.Append(k + "=" + v + "&");
            }
            sb.Append("key=" + this._key);
            var sign = Plugin.SecurityHelper.MD5EncryptWeChat(sb.ToString(), Charset).ToUpper();
            error = "sign = " + sign + "\r\n xmlMap[sign]=" + XmlMap["sign"].ToString();
            return sign.Equals(XmlMap["sign"]);
        }

        ///// <summary>
        ///// 获取编码方式
        ///// </summary>
        ///// <returns></returns>
        //protected virtual string GetCharset()
        //{
        //    //return "UTF-8";
        //    try
        //    {
        //        return HttpHelper.GetRequestEncoding(_accessor.HttpContext.Request).BodyName;
        //    }
        //    catch (Exception)
        //    {
        //        return "UTF-8";
        //    }
        //}
    }
}
