using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Serialization;
using Hncore.Infrastructure.Common;
using Hncore.Pass.PaymentCenter.Domain;
using Hncore.Pass.PaymentCenter.Model;
using XC.RSAUtil;

namespace Hncore.Pass.PaymentCenter.WeiFuTong
{
    [XmlRoot("xml", Namespace = "")]
    public class WeiFuTongRequestBase : WeiFuTongDTOBase
    {
        /// <summary>
        /// 接口类型
        /// </summary>
        [XmlElement("service")]
        public string Service { get; set; }

        /// <summary>
        /// 门店编号，由平台分配
        /// </summary>
        [XmlElement("mch_id")]
        public string MchId { get; private set; }

        /// <summary>
        /// 连锁商户号
        /// </summary>
        [XmlElement("groupno")]
        public string GroupNo { get; private set; }

        /// <summary>
        /// 可选值 UTF-8 ，默认为 UTF-8
        /// </summary>
        [XmlElement("charset")]
        public string Charset { get; set; } = "UTF-8";

        private MchInfo _mchInfo;

        public MchInfo MchInfo
        {
            get => _mchInfo;
            set
            {
                _mchInfo = value;
                MchId = value.MchId;
                GroupNo = value.GroupNo;
            }
        }

        private PaymentChannel _paymentChannel;


        public PaymentChannel PaymentChannel
        {
            get => _paymentChannel;
            set
            {
                _paymentChannel = value;

                if (value == PaymentChannel.QuanFuTong)
                {
                    SignType = "RSA_1_1";
                }
            }
        }

        public WeiFuTongRequestBase(string service)
        {
            Service = service;
        }

        protected virtual SortedDictionary<string, string> ToSortDic()
        {
            var type = GetType();
            var properties = type.GetProperties();

            SortedDictionary<string, string> dic = new SortedDictionary<string, string>();

            foreach (var property in properties)
            {
                var xmlAttr = property.GetCustomAttributes(typeof(XmlElementAttribute), false);

                if (!xmlAttr.Any())
                {
                    continue;
                }

                string name = ((XmlElementAttribute) xmlAttr[0]).ElementName;

                object valueObj = property.GetValue(this, null);

                if (valueObj == null)
                {
                    continue;
                }

                string value = valueObj.ToString();

                if (!string.IsNullOrEmpty(value))
                {
                    dic[name] = value;
                }
            }

            return dic;
        }

        protected virtual void CreateSign(MchInfo mchInfo)
        {
            Sign = "";
            string sign = "";

            foreach (var item in ToSortDic())
            {
                sign += item.Key + "=" + item.Value + "&";
            }

            if (SignType == "MD5")
            {
                sign += "key=" + mchInfo.Key;
                sign = SecurityHelper.GetMd5Hash(sign).ToUpper();
            }
            else if (SignType == "RSA_1_1")
            {
                sign = sign.Substring(0, sign.Length - 1);

                sign = new RsaPkcs8Util(Encoding.UTF8
                        , mchInfo.RSAPublicKey
                        , mchInfo.RSAPrivateKey)
                    .SignData(sign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
            }


            Sign = sign;
        }

        public string ToXml()
        {
            CreateSign(MchInfo);

            StringBuilder sb = new StringBuilder("<xml>\n");

            foreach (var item in ToSortDic())
            {
                string key = item.Key;
                sb.Append("\t<").Append(key).Append("><![CDATA[").Append(item.Value).Append("]]></").Append(key)
                    .Append(">\n");
            }

            return sb.Append("</xml>").ToString();
        }
    }
}