using Hncore.Infrastructure.Common;
using Hncore.Infrastructure.Extension;
using Hncore.Infrastructure.Serializer;
using Hncore.Infrastructure.WebApi;
using Hncore.Pass.PaymentCenter.Domain;
using Hncore.Pass.PaymentCenter.Pay.WxPay;
using Hncore.Pass.PaymentCenter.Request.WechatJsPay;
using Hncore.Pass.PaymentCenter.Service;
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System.Threading.Tasks;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Exceptions;
using Aliyun.Acs.Core.Http;
using Aliyun.Acs.Core.Profile;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Alipay.AopSdk.Core;
using System.Collections.Generic;
using Alipay.AopSdk.Core.Util;
using System;
using Microsoft.AspNetCore.Http;

namespace Hncore.Pass.PaymentCenter.Controllers
{
    /// <summary>
    /// 微信小程序、公众号支付
    /// </summary>
    [ApiVersion("1.0")]
    [Route("api/paymentcenter/v{version:apiVersion}/AliPay/[action]")]
    public class AliPayController : PaymentControllerBase
    {
        private PaymentRecordService m_PaymentRecordService;    
        private WxPayClient m_WxPayClient;
        DefaultAopClient _aopClient;
        public AliPayController(PaymentRecordService paymentRecordService
            , WxPayClient _WxPayClient, TenantService _TenantService, IConfiguration _Configuration):base(_TenantService, _Configuration)
        {
            m_PaymentRecordService = paymentRecordService;        
            m_WxPayClient = _WxPayClient;
        }
        [HttpPost, InternalApiAuth]
        public async Task<ApiResult> CreateOrder([FromBody] CreateOrderRequest request)
        {           

            LogHelper.Trace($"微信支付，收到支付请求", request.ToJson(true));
            request.AppId = "wx18683d61ce7da361";
            //增加支付记录
            var entity = request.MapTo<PaymentRecord>();
            entity.Openid = request.UserOpenId;           
              PaymentRecord paymentRecord = await m_PaymentRecordService.CreatePaymentRecord(entity);
            paymentRecord.PaymentChannel = PaymentChannel.WxPay;
            //todo
            var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId
                , paymentRecord.StoreId
                , paymentRecord.PaymentChannel);

            //发起支付

            var APP_ID = "";
            var APP_PRIVATE_KEY = "";
            var CHARSET = "";
            var ALIPAY_PUBLIC_KEY = "";

            // 组装业务参数model
            AlipayTradePagePayModel model = new AlipayTradePagePayModel
            {
                Body = request.Body,
                Subject = request.Body,
                TotalAmount =request.TotalFee.ToString(),
                OutTradeNo = request.OrderId,
                ProductCode = "FAST_INSTANT_TRADE_PAY"//QUICK_WAP_PAY
            };

            AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
            // 设置同步回调地址
            aliRequest.SetReturnUrl($"http://{Request.Host}/Pay/Callback");
            // 设置异步通知接收地址
            aliRequest.SetNotifyUrl("");
            // 将业务model载入到request
            aliRequest.SetBizModel(model);

           var  _aopClient = new DefaultAopClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY);

            var response = _aopClient.PageExecute(aliRequest);

            return Success();
        }

        #region 支付异步回调通知

        /// <summary>
        /// 支付异步回调通知 需配置域名 因为是支付宝主动post请求这个action 所以要通过域名访问或者公网ip
        /// </summary>
        public async void Notify()
        {
            /* 实际验证过程建议商户添加以下校验。
			1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
			2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
			3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
			4、验证app_id是否为该商户本身。
			*/
            Dictionary<string, string> sArray = GetRequestPost();
            if (sArray.Count != 0)
            {
                // bool flag = AlipaySignature.RSACheckV1(sArray, Options.AlipayPublicKey, Options.CharSet, Options.SignType, false);      
                bool flag = AlipaySignature.RSACheckV1(sArray, "", "", "", false);             
                if (flag)
                {
                    //交易状态
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                    //如果有做过处理，不执行商户的业务程序

                    //注意：
                    //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                    Console.WriteLine(Request.Form["trade_status"]);

                    await Response.WriteAsync("success");
                }
                else
                {
                    await Response.WriteAsync("fail");
                }
            }
        }

        #endregion

        #region 支付同步回调

        /// <summary>
        /// 支付同步回调
        /// </summary>
        [HttpGet]
        public IActionResult Callback()
        {
            /* 实际验证过程建议商户添加以下校验。
			1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
			2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
			3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
			4、验证app_id是否为该商户本身。
			*/
            Dictionary<string, string> sArray = GetRequestGet();
            if (sArray.Count != 0)
            {
                bool flag = AlipaySignature.RSACheckV1(sArray, "", "", "", false);
                if (flag)
                {
                    Console.WriteLine($"同步验证通过，订单号：{sArray["out_trade_no"]}");
                   // ViewData["PayResult"] = "同步验证通过";
                }
                else
                {
                    Console.WriteLine($"同步验证失败，订单号：{sArray["out_trade_no"]}");
                   // ViewData["PayResult"] = "同步验证失败";
                }
            }
            return Content("");
        }

        #endregion


        private Dictionary<string, string> GetRequestGet()
        {
            Dictionary<string, string> sArray = new Dictionary<string, string>();

            ICollection<string> requestItem = Request.Query.Keys;
            foreach (var item in requestItem)
            {
                sArray.Add(item, Request.Query[item]);

            }
            return sArray;

        }
        private Dictionary<string, string> GetRequestPost()
        {
            Dictionary<string, string> sArray = new Dictionary<string, string>();

            ICollection<string> requestItem = Request.Form.Keys;
            foreach (var item in requestItem)
            {
                sArray.Add(item, Request.Form[item]);

            }
            return sArray;

        }

    }
}