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.Response;
using Hncore.Pass.PaymentCenter.Response.PaymentRecord;
using Hncore.Pass.PaymentCenter.Service;
using Hncore.Pass.PaymentCenter.WeiFuTong;
using Hncore.Pass.PaymentCenter.WeiFuTong.Notify;
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Hncore.Pass.PaymentCenter.Controllers
{
    [ApiVersion("1.0")]
    [Route("api/paymentcenter/v{version:apiVersion}/Payment/[action]")]
    public class PaymentController : PaymentControllerBase
    {        
        private PaymentRecordService m_PaymentRecordService;
        private WeiFuTongService m_WeiFuTongService;
        private InternalNotifySerivce m_InternalNotifySerivce;

        private WxPayClient m_WxPayClient { get; set; }

        public PaymentController(
              PaymentRecordService _PaymentRecordService
            , InternalNotifySerivce internalNotifySerivce
            , TenantService _TenantService
            , WxPayClient _WxPayClient
            , WeiFuTongService weiFuTongService
            , IConfiguration _Configuration) : base(_TenantService, _Configuration)
        {
           // m_WeiFuTongService = weiFuTongService;        
            m_PaymentRecordService = _PaymentRecordService;
            m_InternalNotifySerivce = internalNotifySerivce;
            m_WxPayClient = _WxPayClient;
        }

        private async Task<QueryOrderResponse> QueryOrderByPaymentRecordAsync(PaymentRecord paymentRecord)
        {
            QueryOrderResponse result = null;

            //威富通的订单
            if (paymentRecord.PaymentChannel == PaymentChannel.WeiFuTong
                || paymentRecord.PaymentChannel == PaymentChannel.QuanFuTong
                && paymentRecord.FromPos==0)
            {
                var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId
                    , paymentRecord.StoreId
                    , paymentRecord.PaymentChannel);

                result = await m_WeiFuTongService.QueryOrderAsync(paymentRecord, mchInfo);

                await UofCommitAsync();
            }

            return result;
        }

        /// <summary>
        /// 通用订单查询
        /// </summary>
        /// <param name="orderNo"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> QueryOrder(string orderNo = "", int? recordId = 0)
        {
            PaymentRecord paymentRecord = null;

            if (recordId == null || recordId == 0)
            {
                paymentRecord = await m_PaymentRecordService.Query(false)
                    .OrderByDescending(t => t.Id)
                    .FirstOrDefaultAsync(t => t.OrderId == orderNo);
            }
            else if (recordId > 0)
            {
                paymentRecord = await m_PaymentRecordService.GetById(recordId.ToInt());
            }

            CheckHelper.NotNull(paymentRecord, "支付记录不存在");

            var result = await QueryOrderByPaymentRecordAsync(paymentRecord);

            if (result == null)
            {
                return Error("未知的支付渠道");
            }

            return Success(result);
        }


        /// <summary>
        /// 根据orderid查询一条支付记录
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetDetail([FromQuery] string orderId)
        {
            return Success(await QueryPaymentRecordByOrderIdResponse.Query(
                m_PaymentRecordService.Query(false)
                , orderId)
            );
        }

        /// <summary>
        /// 威富通、全付通 接收通知
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> HWCNotify()
        {
            try
            {
                string xml = "";

                if (Request.Body.CanSeek)
                {
                    Request.Body.Position = 0;
                }

                using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body))
                {
                    xml = reader.ReadToEnd();
                }

                LogHelper.Trace("收到威富通支付通知，原始数据：", $"{xml}");


                var notifyEntity = XML.XmlDeserialize<NotifyResponse>(xml);

                // 给支付平台的订单号为支付记录id
                int paymentRecordId = notifyEntity.OutTradeNo.ToInt();

                var paymentRecord = await m_PaymentRecordService.GetById(paymentRecordId);

                var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId, paymentRecord.StoreId,
                    paymentRecord.PaymentChannel);

                Util.CheckSignFromXml(xml, mchInfo);

                if (notifyEntity.PayResult == 0) //支付成功
                {
                    paymentRecord.SetPaySuccessed(notifyEntity.TransactionId, notifyEntity.GetPaySuccessTime());
                    paymentRecord.SetPaymentTypeFromTradeType(notifyEntity.TradeType);
                }
                else
                {
                    paymentRecord.SetPayFailed();
                }

                await m_PaymentRecordService.Update(paymentRecord);

                var status = notifyEntity.PayResult == 0 ? "成功" : "失败";


                LogHelper.Info("威富通回调信息：",
                    $"支付记录Id：{paymentRecord.Id}\n订单号：{paymentRecord.OrderId}\n交易号：{paymentRecord.TransactionId}\n支付状态：{status}\n发起时间：{paymentRecord.RequestTime.Format("yyyy-MM-dd HH:mm:ss")}\n付款成功时间：{notifyEntity.GetPaySuccessTime().Format("yyyy-MM-dd HH:mm:ss")}\n收到通知时间：{DateTime.Now.Format("yyyy-MM-dd HH:mm:ss")}\n总用时：{(DateTime.Now - paymentRecord.RequestTime).TotalSeconds}秒");

                if (notifyEntity.PayResult == 0)
                {
                    //发起内部通知
                    await m_InternalNotifySerivce.Notify(paymentRecord);
                }
            }
            catch (Exception e)
            {
                LogHelper.Error("威富通通知处理失败", e);

                return "fail";
            }

            return "success";
        }

        /// <summary>
        /// 微信支付回调 接收通知
        /// </summary>
        /// <returns></returns>
        [HttpPost, AllowAnonymous]
        public async Task<string> Notify()
        {
            try
            {
                string xml = "";
                LogHelper.Trace("微信支付回调开始","Notify");
                if (Request.Body.CanSeek)
                {
                    Request.Body.Position = 0;
                }

                using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body))
                {
                    xml = reader.ReadToEnd();
                }

                LogHelper.Trace("微信支付回调，原始数据：", $"{xml}");

                WxPayChecker payData = new WxPayChecker();

                payData.FromXmlNoCheckSign(xml);

                if (!payData.IsSet("out_trade_no"))
                {
                    return FailXml();
                }

                // 给支付平台的订单号为支付记录id
                string orderId = payData["out_trade_no"];

                string TransactionId = payData["transaction_id"];

                var paymentRecord = await m_PaymentRecordService.GetOneByOrderId(orderId);
                if (paymentRecord.TransactionId.NotHas())
                {
                    paymentRecord.TransactionId = TransactionId;
                    await m_PaymentRecordService.Update(paymentRecord);
                }

                var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId, paymentRecord.StoreId,
                    paymentRecord.PaymentChannel);
                payData.MchKey = mchInfo.Key;

                var queryRet = await m_WxPayClient.OrderQuery(new WxJsPayOrderQueryRequest()
                {
                    AppId = paymentRecord.Appid,
                    MchId = mchInfo.MchId,
                    NonceStr = payData.GenerateNonceStr(),
                    TransactionId = TransactionId
                }, mchInfo);
                if (!queryRet) return FailXml();
              
                if (!payData.CheckSign()) return FailXml();

                paymentRecord.PaymentStatus = PaymentStatus.OkPay;
                paymentRecord.UpdateTime = DateTime.Now;
                paymentRecord.PaymentCompletionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                await m_PaymentRecordService.Update(paymentRecord);
                //发起内部通知
                await m_InternalNotifySerivce.Notify(paymentRecord);
            }
            catch (Exception e)
            {
                LogHelper.Error("微信支付通知处理失败", e);

                return FailXml();
            }

            return SuccessXml();
        }

        public string FailXml()
        {
            return "<xml><return_code>FAIL</return_code> </xml>";
        }

        private string SuccessXml()
        {
            return "<xml><return_code>SUCCESS</return_code> </xml>";
        }
    }
}