using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

using Newtonsoft.Json.Linq;

namespace HuanMeng.DotNetCore.WeChat
{

    /// <summary>
    /// 
    /// </summary>
    public class WXBizDataCrypt
    {
        private string appId;
        private string sessionKey;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="appId">小程序的 appId</param>
        /// <param name="sessionKey">用户在小程序登录后获取的会话密钥</param>
        public WXBizDataCrypt(string appId, string sessionKey)
        {
            this.appId = appId;
            this.sessionKey = sessionKey;
        }

        /// <summary>
        /// 检验数据的真实性，并且获取解密后的明文
        /// </summary>
        /// <param name="encryptedData">加密的用户数据</param>
        /// <param name="iv">与用户数据一同返回的初始向量</param>
        /// <param name="data">解密后的原文</param>
        /// <returns>成功0，失败返回对应的错误码</returns>
        public int DecryptData(string encryptedData, string iv, out string data)
        {
            data = null;

            // 检查 sessionKey 长度
            if (sessionKey.Length != 24)
            {
                return ErrorCode.IllegalAesKey;
            }

            // 检查 iv 长度
            if (iv.Length != 24)
            {
                return ErrorCode.IllegalIv;
            }

            try
            {
                byte[] aesKey = Convert.FromBase64String(sessionKey);
                byte[] aesIV = Convert.FromBase64String(iv);
                byte[] aesCipher = Convert.FromBase64String(encryptedData);

                using (Aes aesAlg = Aes.Create())
                {
                    aesAlg.Key = aesKey;
                    aesAlg.IV = aesIV;
                    aesAlg.Mode = CipherMode.CBC;
                    aesAlg.Padding = PaddingMode.PKCS7;

                    using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
                    {
                        using (MemoryStream msDecrypt = new MemoryStream(aesCipher))
                        {
                            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                            {
                                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                                {
                                    // 解密后的明文
                                    data = srDecrypt.ReadToEnd();
                                }
                            }
                        }
                    }
                }

                JObject dataObj = JObject.Parse(data);

                // 检查 appId
                if (dataObj["watermark"]["appid"].ToString() != this.appId)
                {
                    return ErrorCode.IllegalBuffer;
                }

                return ErrorCode.OK;
            }
            catch
            {
                return ErrorCode.IllegalBuffer;
            }
        }
    }

    public static class ErrorCode
    {

        public const int OK = 0;
        public const int IllegalAesKey = -41001;
        public const int IllegalIv = -41002;
        public const int IllegalBuffer = -41003;
    }

    public class WXBizDataCryptModel
    {
        public WXBizDataCryptModel() { }
        /// <summary>
        /// 
        /// </summary>
        public string? EncryptedData;
        /// <summary>
        /// 
        /// </summary>
        public string? Iv;


        public int UserId { get; set; }
    }

}
