using System;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Security;
using System.Collections.Generic;

using System.Threading;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Specialized;
using ASHermed.SinoInterface.Tools;
using Newtonsoft.Json;
using PoJun.Util.Webs.Clients;

namespace ASHermed.SinoInterface.IFramework
{
    /// <summary>
    /// HTTP请求帮助
    /// </summary>
    public class HttpClientHelper
    {
        private ILogger<HttpClientHelper> _logger;
        private IHttpClientFactory _httpClientFactory;
        public HttpClientHelper(ILogger<HttpClientHelper> logger, IHttpClientFactory httpClientFactory)
        {
            _logger = logger;
            _httpClientFactory = httpClientFactory;
        }
        /// <summary>
        /// 同步GET请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="timeout">请求响应超时时间，单位/s(默认100秒)</param>
        /// <returns></returns>
        public string HttpGet(string url, HttpOptions httpOptions = null)
        {
            Task<string> result = HttpGetAsync(url, httpOptions);
            return result.Result;
        }
        public T HttpGet<T>(string url, HttpOptions httpOptions = null)
        {
            Task<T> result = HttpGetAsync<T>(url, httpOptions);
            return result.Result;
        }
        public async Task<T> HttpGetAsync<T>(string url, HttpOptions httpOptions = null)
        {
            string result = await HttpGetAsync(url,  httpOptions);
            return DeserializeResult<T>(result);
        }
        /// <summary>
        /// 异步GET请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="timeout">请求响应超时时间，单位/s(默认100秒)</param>
        /// <returns></returns>
        public async Task<string> HttpGetAsync(string url, HttpOptions httpOptions = null)
        {
            if (httpOptions == null)
            {
                httpOptions = new HttpOptions();
            }
            Stopwatch sw = null;
            if (httpOptions.RecordLog)
            {
                sw = new Stopwatch();
                sw.Start();
            }
            string result = "";
            try
            {
                _logger.LogInformation("HttpGetAsync URL "+ url+ " HttpGetAsync httpOptions "+ httpOptions.ToJson());
                HttpClient client = _httpClientFactory.CreateClient();
                if (httpOptions.Headers != null)
                {
                    foreach (KeyValuePair<string, string> header in httpOptions.Headers)
                    {
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }
                if (httpOptions.Timeout > 0)
                {
                    client.Timeout = TimeSpan.FromMilliseconds(httpOptions.Timeout);
                }
                byte[] resultBytes = await client.GetByteArrayAsync(url);
                result = Encoding.UTF8.GetString(resultBytes);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, httpOptions.LogName + "HttpGetAsync异常");
                throw ex;
            }
            finally
            {
                if (httpOptions.RecordLog)
                {
                    sw.Stop();
                    _logger.LogInformation(httpOptions.LogName + "HttpGetAsync(" + sw.ElapsedMilliseconds.ToString() + ") 请求:" + url + ",HTTP请求返回:" + result);
                }
            }
            return result;
        }

        #region HttpPost

      

        /// <summary>
        /// 同步POST请求 返回字符串
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="httpOptions"></param>
        /// <returns></returns>
        public string HttpPost(string url, string postData, HttpOptions httpOptions = null)
        {
            var result = HttpPostAsync(url, postData, httpOptions);
            return result.Result;
        }
        //public string HttpPost(string url, NameValueCollection nameValueCollection, HttpOptions httpOptions = null)
        //{
        //    string data = "";
        //    try
        //    {
        //        var result = HttpPostAsync(url, nameValueCollection, httpOptions);
        //        data = result.Result;
        //    }
        //    catch (Exception ex)
        //    {
        //        _logger.LogCritical(ex, $"HttpPost异常url:{url}");
        //        data = "";
        //    }
        //    return data;
        //}
        /// <summary>
        /// 同步POST请求 返回对像
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="httpOptions"></param>
        /// <returns></returns>
        public T HttpPost<T>(string url, string postData, HttpOptions httpOptions = null)
        {
            Task<T> result = HttpPostAsync<T>(url, postData, httpOptions);
            return result.Result;
        }
        //public T HttpPost<T>(string url, NameValueCollection nameValueCollection, HttpOptions httpOptions = null)
        //{
        //    var result = HttpPost(url, nameValueCollection, httpOptions);
        //    return DeserializeResult<T>(result);
        //}


        //public async Task<string> HttpPostAsync(string url, NameValueCollection nameValueCollection, HttpOptions httpOptions = null)
        //{
        //    if (httpOptions == null)
        //    {
        //        httpOptions = new HttpOptions();
        //    }
        //    Stopwatch sw = null;
        //    if (httpOptions.RecordLog)
        //    {
        //        sw = new Stopwatch();
        //        sw.Start();
        //    }
        //    string result = "";
        //    try
        //    {
        //        var client = _httpClientFactory.CreateClient();
        //        if (httpOptions.Headers != null)
        //        {
        //            foreach (KeyValuePair<string, string> header in httpOptions.Headers)
        //            {
        //                client.DefaultRequestHeaders.Add(header.Key, header.Value);
        //            }
        //        }
        //        if (httpOptions.Timeout > 0)
        //        {
        //            client.Timeout = new TimeSpan(0, 0, httpOptions.Timeout);
        //        }
        //        if (httpOptions.ContentType != null)
        //        {
        //            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(httpOptions.ContentType);
        //        }
        //        using (HttpResponseMessage responseMessage = await client.PostAsync(url, content))
        //        {
        //            byte[] resultBytes = await responseMessage.Content.ReadAsByteArrayAsync();
        //            result = Encoding.UTF8.GetString(resultBytes);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        _logger.LogInformation(ex, "HttpPostAsync异常");
        //        throw ex;
        //    }
        //    finally
        //    {
        //        if (httpOptions.RecordLog)
        //        {
        //            sw.Stop();
        //            _logger.LogInformation("HttpPostAsync(" + sw.ElapsedMilliseconds.ToString() + ") 请求:" + url + ",HTTP请求返回:" + result);
        //        }
        //    }
        //    return result;

        //}

        //public async Task<string> HttpPostAsync(string url, string postData, HttpOptions httpOptions = null)
        //{
        //    if (httpOptions == null)
        //    {
        //        httpOptions = new HttpOptions();
        //    }
        //    return  await HttpPostAsync(url, content, httpOptions);
        //   ;
        //}

        public async Task<T> HttpPostAsync<T>(string url, string postData, HttpOptions httpOptions = null)
        {
            string  result =await HttpPostAsync(url, postData, httpOptions);
            return DeserializeResult<T>(result);
        }
        /// <summary>
        /// 异步POST请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="httpOptions"></param>
        /// <returns></returns>
        public async Task<string> HttpPostAsync(string url, string postData, HttpOptions httpOptions = null)
        {
            if (httpOptions == null)
            {
                httpOptions = new HttpOptions();
            }
            Stopwatch sw = null;
            if (httpOptions.RecordLog)
            {
                sw = new Stopwatch();
                sw.Start();
            }
            string result = "";
            try
            {
                HttpClient client = _httpClientFactory.CreateClient();
                HttpContent content = new StringContent(postData ?? "", httpOptions?.Encoding ?? Encoding.UTF8);
                if (httpOptions.Headers != null)
                {
                    foreach (KeyValuePair<string, string> header in httpOptions.Headers)
                    {
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }
                if (httpOptions.Timeout > 0)
                {
                    client.Timeout = TimeSpan.FromMilliseconds(httpOptions.Timeout);
                }
                if (httpOptions.ContentType != null)
                {
                    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(httpOptions.ContentType);
                }
                using (HttpResponseMessage responseMessage = await client.PostAsync(url, content))
                {
                    byte[] resultBytes = await responseMessage.Content.ReadAsByteArrayAsync();
                    result = Encoding.UTF8.GetString(resultBytes);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, httpOptions.LogName + "HttpPostAsync异常");
                throw ex;
            }
            finally
            {
                if (httpOptions.RecordLog)
                {
                    sw.Stop();
                    _logger.LogInformation(httpOptions.LogName+"HttpPostAsync(" + sw.ElapsedMilliseconds.ToString() + ") 请求:" + url + ",HTTP请求返回:" + result);
                }
            }
            return result;
        }

        #endregion

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        /// <returns></returns>
        private T DeserializeResult<T>(string result)
        {
            if (result.IsNullOrEmpty())
            {
                _logger.LogCritical($"httpclient DeserializeResult请求返回结果为空");
                return default(T);
            }
            var data = JsonConvert.DeserializeObject<T>(result);
            //if (typeof(BaseResp).GetTypeInfo().IsAssignableFrom(data.GetType()))
            //{
            //    var o = data as BaseResp;
            //    if (o.Code != 0)
            //    {
            //        _logger.LogCritical($"返回的code不为0");
            //    }
            //}
            return data;
        }
    }

    public class HttpOptions
    {
        public string ContentType { get; set; } = "application/json";
        /// <summary>
        /// 超时设置：单位毫秒，默认5000
        /// </summary>
        public int Timeout { get; set; } = 5000;
        /// <summary>
        /// 是否记录请求及返回日志
        /// </summary>
        public bool RecordLog { get; set; } = true;
        public string LogName { get; set; } = String.Empty;
        public Encoding Encoding { get; set; }

        public Dictionary<string, string> Headers = null;

    }
}