using Hncore.Infrastructure.Common;
using Hncore.Infrastructure.Extension;
using Hncore.Infrastructure.Serializer;
using Hncore.Infrastructure.Service;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;

namespace Hncore.Pass.PaymentCenter.Domain
{
    /// <summary>
    /// 内部通知
    /// </summary>
    public class InternalNotifySerivce : ServiceBase<PaymentNotify>, IFindService
    {
        private IHttpClientFactory m_httpClientFactory;
        ServiceHttpClient m_ServiceHttpClient;
        public InternalNotifySerivce(PaymentContext dbContext
            , ServiceHttpClient _ServiceHttpClient
            , IHttpContextAccessor httpContextAccessor
            , IHttpClientFactory _httpClientFactory) : base(dbContext, httpContextAccessor)
        {
            m_httpClientFactory = _httpClientFactory;
            m_ServiceHttpClient = _ServiceHttpClient;
        }       


        /// <summary>
        /// 发起内部通知，没有支付记录
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public async Task Notify(string url, object postData)
        {
            bool success;
            string responseData = "";

            try
            {
                Stopwatch st = new Stopwatch();
                st.Start();

                responseData = await m_httpClientFactory
                    .CreateClient(TimeSpan.FromMinutes(5))
                    .PostAsJsonGetString(url, postData);

                st.Stop();

                LogHelper.Trace("支付内部通知请求：",
                    $"{url}\n\n{postData.ToJson(true)}\n\n响应：\n{responseData}\n\n用时：{st.ElapsedMilliseconds}毫秒");

                if (responseData.ToLower() != "success")
                {
                    success = false;
                }
                else
                {
                    success = true;
                }
            }
            catch (Exception e)
            {
                LogHelper.Error($"支付内部通知异常，{e.Message}", e);

                success = false;
            }

            if (!success)
            {
                await this.Add(new PaymentNotify()
                {
                    PaymentRecordId = 0,
                    Url = url,
                    ResponseData = responseData,
                    PostData = postData.ToJson(),
                    RetryCount = 0,
                    NotifyType= NotifyType.Faild
                });
            }
        }


        /// <summary>
        /// 发起内部通知，有支付记录
        /// </summary>
        /// <param name="paymentRecord"></param>
        /// <returns></returns>
        public async Task Notify(PaymentRecord paymentRecord)
        {
            if (paymentRecord.CallbackStatus == CallbackStatus.Finished)
            {
                return;
            }

            bool success;

            string responseData = "";

            string callBackUrl = paymentRecord.CallbackUrl;

            if (!callBackUrl.Has())
            {
                //LogHelper.Warn("该支付记录没有回调地址", paymentRecord.ToJson(true));
                return;
            }

            if (!callBackUrl.StartsWith("http"))
            {
                LogHelper.Warn("该支付记录回调地址异常", paymentRecord.ToJson(true));
                return;
            }

            callBackUrl = UrlHelper.SetUrlParam(callBackUrl, new {PaymentType = (int) paymentRecord.PaymentType});

            var postData = new
            {
                Data = new
                {
                    Attach = paymentRecord.Attach,
                    OrderId = paymentRecord.OrderId
                }
            };

            try
            {
                Stopwatch st = new Stopwatch();
                st.Start();

               var client= m_ServiceHttpClient.CreateInternalClient();
                responseData = await  client.PostAsJsonGetString(callBackUrl, postData);

                st.Stop();

                LogHelper.Trace("支付内部通知请求：",
                    $"{callBackUrl}\n\n{postData.ToJson(true)}\n\n响应：\n{responseData}\n\n用时：{st.ElapsedMilliseconds}毫秒");

                if (responseData.ToLower() != "success")
                {
                    success = false;
                }
                else
                {
                    success = true;
                    paymentRecord.CallbackStatus = CallbackStatus.Finished;
                }
            }
            catch (Exception e)
            {
                LogHelper.Error($"支付内部通知异常，{e.Message}", e);

                success = false;
            }

            if (!success)
            {
                var any = await this.Query(true).AnyAsync(t => t.Id == paymentRecord.Id);

                if (!any)
                {
                    await this.Add(new PaymentNotify()
                    {
                        PaymentRecordId = paymentRecord.Id,
                        Url = callBackUrl,
                        ResponseData = responseData,
                        PostData = postData.ToJson(),
                        RetryCount = 0,
                        NotifyType=NotifyType.Faild
                    });
                }
            }
        }
    }
}