using LifePayment.Domain.Shared;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;

namespace LifePayment.Domain
{
    public class ACOOLYClient : DomainService
    {
        private const string ACOOLYClientName = "ACOOLYClientName";
        private readonly ILogger<ACOOLYClient> _logger;
        private readonly ACOOLYOption options;
        private readonly JsonSerializerSettings jsonSetting = new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore
        };

        public ACOOLYClient(ILogger<ACOOLYClient> logger, IOptionsMonitor<ACOOLYOption> optionsMonitor)
        {
            _logger = logger;
            options = optionsMonitor.CurrentValue;
        }

        protected IHttpClientFactory HttpClientFactory => LazyServiceProvider.LazyGetRequiredService<IHttpClientFactory>();

        public async Task<TResult> PostAsync<TInput, TResult>(TInput input)
        {
            try
            {
                var client = HttpClientFactory.CreateClient(ACOOLYClientName);
                client.DefaultRequestHeaders.Add("x-api-accesskey", options.Accesskey);
                client.DefaultRequestHeaders.Add("x-api-signType", "MD5");
                // ToDo 参数可能存在排序后再加密,需要联调确认
                var body = JsonConvert.SerializeObject(input, jsonSetting);
                if (body.Length < 2000)
                {
                    _logger.LogError("请求ACOOLY接口:" + body);
                }
                var data = new StringContent(body, Encoding.UTF8, "application/json");
                data.Headers.Add("x-api-sign", GetMD5Data(body));
                var responseMessage = await client.PostAsync(options.ServerHost, data);
                var str = await responseMessage.Content.ReadAsStringAsync();
                if (!body.Contains(ACOOLYConstant.Sevice.ElectricSupportArea))
                {
                    _logger.LogError("ACOOLY接口返回:" + str);
                }

                var result = JsonConvert.DeserializeObject<TResult>(str);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError("ACOOLY接口错误:" + ex.Message);
                return default(TResult);
            }

        }

        public string GetMD5Data(string jsonData) //POST请求接口,使用此方法计算签名
        {
            string dataMD5 = "";
            if (!string.IsNullOrEmpty(jsonData))
            {
                var str = jsonData + options.SecrtKey;
                dataMD5 = CreateMD5Hash(str);
            }

            return dataMD5;
        }

        #region 私有方法

        private string CreateMD5Hash(string input)
        {
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("x2"));
            }

            return sb.ToString();
        }
        #endregion
    }

}