using System;
using System.Collections.Generic;
using Library;
using LitJson;
using System.Linq;
using MySystem.PxcModels;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using System.Text;

namespace MySystem
{
    public class WeChatPayBackService
    {
        public readonly static WeChatPayBackService Instance = new WeChatPayBackService();
        private WeChatPayBackService()
        { }

        public void Start(JobMqMsg jobInfo)
        {
            string content = "";
            try
            {
                dosomething();
                // string Msg = "success";
                // jobInfo.Status = Msg == "success" ? 1 : 0;
                // jobInfo.Msg = Msg == "success" ? "执行完成" : Msg;
                // RabbitMQClient.Instance.SendMsg(Newtonsoft.Json.JsonConvert.SerializeObject(jobInfo), "PublicBack");
            }
            catch (Exception ex)
            {
                if (!string.IsNullOrEmpty(content))
                {
                    Dictionary<string, string> data = new Dictionary<string, string>();
                    data.Add("ErrTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                    data.Add("ErrMsg", ex.ToString());
                    Utils.WriteLog(Newtonsoft.Json.JsonConvert.SerializeObject(data), "public_err");
                }
                else
                {
                    Utils.WriteLog(DateTime.Now.ToString() + ":" + ex.ToString(), "public_service");
                }
            }
        }

        public void dosomething()
        {
            bool op = true;
            while (op)
            {
                string content = RedisDbconn.Instance.RPop<string>("WeChatPayBack");
                if (!string.IsNullOrEmpty(content))
                {
                    JsonData jsonObj = JsonMapper.ToObject(content);
                    if (jsonObj.Count > 0)
                    {
                        if (jsonObj["event_type"].ToString() == "TRANSACTION.SUCCESS")
                        {
                            JsonData resource = jsonObj["resource"];
                            //开始解密
                            string WxPayResourceDecryptModel = AesGcmDecrypt(resource["associated_data"].ToString(), resource["nonce"].ToString(), resource["ciphertext"].ToString());
                            // {\"sp_mchid\":\"1611167423\",\"sub_mchid\":\"1622024882\",\"sp_appid\":\"wxe2c051b3e46c0f6f\",\"out_trade_no\":\"2022022621562926396898863\",\"transaction_id\":\"4200001412202202267619496496\",\"trade_type\":\"JSAPI\",\"trade_state\":\"SUCCESS\",\"trade_state_desc\":\"支付成功\",\"bank_type\":\"OTHERS\",\"attach\":\"\",\"success_time\":\"2022-02-26T21:56:42+08:00\",\"payer\":{\"sp_openid\":\"omawy5W6jb0pgPfuKUVs6K3bEhzk\",\"sub_openid\":\"\"},\"amount\":{\"total\":1,\"payer_total\":1,\"currency\":\"CNY\",\"payer_currency\":\"CNY\"}}
                            JsonData orderObj = JsonMapper.ToObject(WxPayResourceDecryptModel);
                            string OrderNo = orderObj["out_trade_no"].ToString();
                            WebCMSEntities db = new WebCMSEntities();
                            ConsumerOrderForNo forNo = db.ConsumerOrderForNo.FirstOrDefault(m => m.OrderNo == OrderNo);
                            if (forNo != null)
                            {
                                ConsumerOrders order = db.ConsumerOrders.FirstOrDefault(m => m.Id == forNo.OrderIds && m.Status == 0);
                                if (order != null)
                                {
                                    order.Status = 1;
                                    order.UpdateDate = DateTime.Now;
                                    order.PayMoney = order.PayMoney;
                                    order.MaxDivi = order.MaxDivi;
                                    db.SaveChanges();
                                    RedisDbconn.Instance.AddList("ConsumerOrdersStat", order.Id);
                                    RedisDbconn.Instance.AddList("ConsumerOrders:Divi:List", order.Id.ToString());
                                    RedisDbconn.Instance.AddRightList("ConsumerOrders:Divi:" + order.MerchantId, order);
                                    // ConsumerOrdersStatService.Instance.Stat(order);
                                }
                            }
                            db.Dispose();
                        }
                    }
                }
                else
                {
                    op = false;
                }
            }
        }

        private string ALGORITHM = "AES/GCM/NoPadding";
        private int TAG_LENGTH_BIT = 128;
        private int NONCE_LENGTH_BYTE = 12;
        private string AES_KEY = "VyULlqfAW2gBfCNfLdupcL7zlha7d93F";//你的v3秘钥

        public string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
        {
            GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
            AeadParameters aeadParameters = new AeadParameters(
                new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)),
                128,
                Encoding.UTF8.GetBytes(nonce),
                Encoding.UTF8.GetBytes(associatedData));
            gcmBlockCipher.Init(false, aeadParameters);

            byte[] data = Convert.FromBase64String(ciphertext);
            byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
            int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
            gcmBlockCipher.DoFinal(plaintext, length);
            return Encoding.UTF8.GetString(plaintext);
        }
    }
}