using System;
using System.Collections.Generic;
using System.Linq;
using AdapayCore;
using AdapaySDK;
using Mall.CacheManager.AppletWeChat;
using Mall.CacheManager.User;
using Mall.Common;
using Mall.Common.API;
using Mall.Common.Plugin;
using Mall.Model.Extend.Product;
using Mall.Module.User;
using Mall.Repository.Education;
using Mall.WebApi.Filter;
using Mall.WeChat.Helper;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Mall.WebApi.Controllers.Adapay
{

    [Route("api/[controller]/[action]")]
    [ApiExceptionFilter]
    [ApiController]
    [EnableCors("AllowCors")]
    public class AdapayController : BaseController
    {

        private readonly UserCommonModule userCommonModule = new UserCommonModule();
        private readonly RB_Trade_ConfigRepository trade_ConfigRepository = new RB_Trade_ConfigRepository();

        private readonly MiniProgramModule miniProgramModule = new MiniProgramModule();

        /// <summary>
        /// 获取支付信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]        
        public ApiResult GetAdapayInfo()
        {
            var rparms = RequestParm;
            var userInfo = AppletUserInfo;
            if (userInfo == null)
            {
                return ApiResult.Failed("请登录");
            }
            var ParmJObj = JObject.Parse(rparms.msg.ToString());
            string pay_channel = ParmJObj.GetStringValue("pay_channel");
            string open_id = ParmJObj.GetStringValue("open_id");// 微信支付 需要openId  对应公众号/小程序openId
            string hb_fq_num = ParmJObj.GetStringValue("hb_fq_num");//支付宝  分期期数  只支持 3，6，12  必须大于等于100元 可用户自己选
            int orderId = ParmJObj.GetInt("orderId", 0);//商城订单ID
            if (orderId <= 0)
            {
                return ApiResult.ParamIsNull("请传递商城订单ID");
            }
            if (string.IsNullOrEmpty(pay_channel))
            {
                return ApiResult.ParamIsNull("请传递支付渠道");
            }
            if ((pay_channel == "wx_pub" || pay_channel == "wx_lite") && string.IsNullOrEmpty(open_id))
            {
                return ApiResult.Failed("请传递微信OpenId");
            }

            var offerModel = userCommonModule.GetAdapayOrderInfo(orderId, userInfo.MallBaseId);
            if (offerModel == null)
            {
                return ApiResult.Failed("订单不存在");
            }
            if (offerModel.OrderStatus != Common.Enum.Goods.OrderStatusEnum.NonPayment)
            {
                return ApiResult.Failed("订单支付状态不正确");
            }

            string appId = InitAdapay(100001);

            var parms = PaymentDemo.CreatePayment(appId, pay_channel, open_id, hb_fq_num, offerModel);
            parms.TryGetValue("status", out object status);
            if (status != null && status.ToString() == "succeeded")
            {
                //获取pay_info信息
                parms.TryGetValue("expend", out object expend);
                string pay_info = "";
                if (pay_channel == "alipay_qr")
                {
                    pay_info = JObject.Parse(expend.ToString()).GetStringValue("qrcode_url");
                    #region 存入缓存
                    try
                    {
                        string payInfoKey = CacheManager.DataStatistic.DataConstant.DATA_AliPay_Order + userInfo.OpenId;
                        var zfbPayList = UserReidsCache.GetOrderPay(payInfoKey);
                        if (zfbPayList.Where(x => x.OrderId == orderId).Any())
                        {
                            //存在
                            foreach (var item in zfbPayList.Where(x => x.OrderId == orderId))
                            {
                                item.PayInfo = pay_info;
                            }
                            UserReidsCache.Set(payInfoKey, JsonHelper.Serialize(zfbPayList), 1800);//储存30分钟
                        }
                        else
                        {
                            zfbPayList.Add(new UserWaitPayInfo()
                            {
                                OrderId = orderId,
                                PayInfo = pay_info
                            });
                            UserReidsCache.Set(payInfoKey, JsonHelper.Serialize(zfbPayList), 1800);//储存30分钟
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Write(ex, "GetOrderPay  支付信息存缓存失败");
                    }
                    #endregion
                }
                else
                {
                    pay_info = JObject.Parse(expend.ToString()).GetStringValue("pay_info");
                }
                return ApiResult.Success("", pay_info);
            }
            else
            {
                return ApiResult.Failed("创建支付失败，请联系管理员");
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="GroupId"></param>
        /// <returns></returns>
        private string InitAdapay(int GroupId)
        {
            var tcModel = trade_ConfigRepository.GetList(new Model.Extend.Education.RB_Trade_Config() { GroupId = GroupId, Type = 1 }).FirstOrDefault();
            string appId = tcModel.AppId;
            MerConfig config = new MerConfig
            {
                apiKey = tcModel.ApiKey,
                privateKey = tcModel.PrivateKey,
                apiMockKey = tcModel.ApiMockKey
            };

            AdapaySDK.Adapay.debug = false;
            AdapaySDK.Adapay.deviceId = "jjsw" + GroupId;
            AdapaySDK.Adapay.isMock = false;
            //商户配置字典
            Dictionary<string, MerConfig> dict = new Dictionary<string, MerConfig>
                {
                    //default商户
                    { "default", config },
                    //另一个商户信息
                    { "yifuyun", config }
                };

            //多商户启动
            AdapaySDK.Adapay.initWithMerConfigs(dict);
            return appId;
        }
    }

    class PaymentDemo
    {

        public static string merchantKey = "yifuyun";
        public static void testPayment(string appId)
        {

            Dictionary<string, Object> payment = testCreatePayment(appId);
            testQueryPayment(appId, (string)payment["id"]);
            testClosePayment(appId, (string)payment["id"]);

            testCreateReverse(appId, "002112019102420545010033426145952493568");

            testReverseList(appId, "002112019102420545010033426145952493568");

            testQueryReverse(appId, "002112019102420545010033426145952493568");
            testCreateConfirm(appId, "002112019102420545010033426145952493568");
            testQueryConfirm(appId, "002112019102420545010033426145952493568");
            testQueryConfirmList(appId, "002112019102420545010033426145952493568");



        }

        public static Dictionary<string, Object> CreatePayment(string appId, string pay_channel, string open_id, string hb_fq_num, RB_Goods_Order_Extend offerModel)
        {
            string courseName = offerModel.DetailList.FirstOrDefault().GoodsName;
            if (!string.IsNullOrEmpty(courseName) && courseName.Length > 15)
            {
                courseName = courseName.Substring(0, 15);
            }
            courseName += "等" + offerModel.DetailList.Count() + "件";
            Dictionary<string, object> dict = new Dictionary<string, object>
            {
                { "pay_amt", offerModel.Income},
                { "app_id", appId },
                { "order_no", DateTime.Now.ToString("yyyyMMdd") + StringUtils.timeStamp() },
                { "pay_channel", pay_channel },
                { "goods_title", "您的待支付订单" },
                { "goods_desc", courseName},
                { "currency", "cny" },
                { "time_expire", DateTime.Now.AddMinutes(30).ToString("yyyyMMddHHmmss")},
                { "description", offerModel.MallBaseId + "|" + offerModel.OrderId},
                { "notify_url", "https://mallapi.oytour.com/api/AdapayCallBack/AdapayCallBackEvent"}
            };
            Dictionary<string, object> expendDict = new Dictionary<string, object>();
            if (pay_channel == "wx_pub" || pay_channel == "wx_lite")
            {
                expendDict.Add("open_id", open_id);//"oT-wi55Qi2eUJxt8UDZxsmsgZ5fc"
            }
            if (!string.IsNullOrEmpty(hb_fq_num))
            {
                expendDict.Add("hb_fq_num", hb_fq_num);//  支付宝分期  目前 只支持3，6，12
            }
            //expendDict.Add("limit_pay", 0);
            dict.Add("expend", expendDict);

            Dictionary<string, object> result = Payment.create(dict, merchantKey);
            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            LogHelper.WriteInfo(JsonConvert.SerializeObject(result, Formatting.None));
            if (!String.IsNullOrEmpty((string)errorCode))
            {
                LogHelper.WriteInfo(JsonConvert.SerializeObject(result, Formatting.None));
            }
            return result;

        }

        public static Dictionary<string, Object> testCreatePayment(string appId)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>
            {
                { "pay_amt", "0.01" },
                { "app_id", appId },
                { "order_no", DateTime.Now.ToString("yyyyMMdd") + StringUtils.timeStamp() },
                { "pay_channel", "alipay_wap" },

                { "goods_title", "测试一下支付" },
                { "goods_desc", "your goods desc" },
                { "currency", "cny" }
            };

            Dictionary<string, object> expendDict = new Dictionary<string, object>();
            expendDict.Add("open_id", "sddddddddfasfdfas");
            expendDict.Add("wx_app_id", appId);
            dict.Add("expend", expendDict);

            Dictionary<string, object> result = Payment.create(dict, merchantKey);
            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine("Payment.create failed");
                Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.create success");
            }


            return result;

        }

        public static Dictionary<string, Object> testQueryPayment(string appId, string paymentId)
        {

            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("payment_id", paymentId);
            Dictionary<string, object> result = Payment.query(dict, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.query success");
            }

            return result;

        }


        public static Dictionary<string, Object> testClosePayment(string appId, string paymentId)
        {

            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("payment_id", paymentId);


            Dictionary<string, object> result = Payment.close(dict, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.close success");
            }
            return result;

        }


        public static Dictionary<string, Object> testReverseList(string appId, string paymentId)
        {

            Dictionary<string, object> reverse = new Dictionary<string, object>();
            reverse.Add("payment_id", paymentId);
            reverse.Add("app_id", appId);
            reverse.Add("page_index", "1");
            reverse.Add("page_size", "20");
            reverse.Add("created_gte", "1571913923");
            reverse.Add("created_lte", "1571913924");
            Dictionary<string, object> result = PaymentReverse.queryList(reverse, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine(" Payment.queryReverseList success");
            }
            return result;

        }


        public static Dictionary<string, Object> testQueryReverse(string appId, string paymentId)
        {

            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("reverse_id", paymentId);

            Dictionary<string, object> result = PaymentReverse.query(dict, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.queryReverse success");
            }
            return result;

        }

        /**
         * 创建撤销对象
         *
         * @param paymentId 要查询的支付id
         * @return 查询的支付对象
         * @ 异常
         */
        public static Dictionary<string, Object> testCreateReverse(string paymentId, string appId)
        {

            Dictionary<string, object> reverse = new Dictionary<string, object>();

            reverse.Add("payment_id", paymentId);
            reverse.Add("app_id", appId);
            reverse.Add("order_no", "csdk_reverse_" + StringUtils.timeStamp());
            reverse.Add("notify_url", "");
            reverse.Add("reverse_amt", "0.01");
            reverse.Add("reason", "reason");
            reverse.Add("expand", "expend");
            reverse.Add("device_info", "device_info");


            Dictionary<string, Object> result = PaymentReverse.create(reverse, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine("Payment.createReverse: \n " + JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.createReverse success");
            }
            return result;
        }

        public static Dictionary<string, Object> testCreateConfirm(string paymentId, string appId)
        {
            Dictionary<string, object> confirm = new Dictionary<string, object>();

            confirm.Add("payment_id", paymentId);
            confirm.Add("order_no", "csdk_confirm_" + StringUtils.timeStamp());
            confirm.Add("confirm_amt", "0.01");
            confirm.Add("description", "description");
            confirm.Add("div_members", "");
            Dictionary<string, object> result = PaymentConfirm.create(confirm, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine("Payment.createConfirm \n" + JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.createConfirm success");
            }
            return result;

        }

        public static Dictionary<string, Object> testQueryConfirm(string appId, string paymentConfirmId)
        {
            Dictionary<string, object> confirm = new Dictionary<string, object>();

            confirm.Add("payment_confirm_id", paymentConfirmId);

            Dictionary<string, Object> result = PaymentConfirm.query(confirm, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine("Payment.queryConfirm \n" + JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.queryConfirm success");
            }
            return result;
        }

        /**
         * 查询确认对象列表
         *
         * @param
         * @return 查询的支付对象
         * @ 异常
         */
        public static Dictionary<string, Object> testQueryConfirmList(string appId, string paymentId)
        {

            Dictionary<string, object> confirm = new Dictionary<string, object>();
            confirm.Add("payment_id", paymentId);
            confirm.Add("app_id", appId);
            confirm.Add("page_index", "1");
            confirm.Add("page_size", "20");
            confirm.Add("created_gte", "1571913867");
            confirm.Add("created_lte", "1571913923");


            Dictionary<string, object> result = PaymentConfirm.queryList(confirm, merchantKey);

            object errorCode = null;
            result.TryGetValue("error_code", out errorCode);

            if (!String.IsNullOrEmpty((string)errorCode))
            {
                Console.WriteLine("Payment.queryConfirmList \n" + JsonConvert.SerializeObject(result, Formatting.None));
            }
            else
            {
                Console.WriteLine("Payment.queryConfirmList success");
            }

            return result;
        }
    }
}