using Binance.TradeRobot.Common.Extensions;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace Binance.TradeRobot.Common.Http
{
    public class RestApiService
    {
        public const string ContentType_Json = "application/json";
        public const string ContentType_Form = "application/x-www-form-urlencoded";
        public TimeSpan TimeOut { get; set; } = new TimeSpan(0, 0, 20);

        private IHttpClientFactory httpClientFactory;

        public RestApiService(IHttpClientFactory httpClientFactory)
        {
            this.httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        /// <param name="apiHost"></param>
        /// <param name="apiPath"></param>
        /// <param name="param"></param>
        /// <param name="requestHeaders"></param>
        /// <param name="httpMethod"></param>
        /// <param name="contentType"></param>
        /// <param name="paramPosition"></param>
        /// <param name="useRandomTimeStamp"></param>
        /// <param name="getResponseHeader"></param>
        /// <param name="httpCompletionOption"></param>
        /// <param name="httpClientName"></param>
        /// <returns></returns>
        public RestApiResult SendRequest(string apiHost,
                                         string apiPath,
                                         object param,
                                         IDictionary<string, string> requestHeaders,
                                         HttpMethod httpMethod,
                                         string contentType = ContentType_Json,
                                         ParamPosition paramPosition = ParamPosition.Body,
                                         bool useRandomTimeStamp = false,
                                         bool getResponseHeader = false,
                                         HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead,
                                         string httpClientName = "")
        {
            //Get和Delete强制使用QueryString形式传参
            if (httpMethod == HttpMethod.Get || httpMethod == HttpMethod.Delete)
                paramPosition = ParamPosition.Query;

            //拼接Url
            var url = string.IsNullOrEmpty(apiPath) ? apiHost :
                                                      $"{apiHost.TrimEnd('/')}/{apiPath.TrimStart('/')}";
            var isCombineParam = false;
            if (paramPosition == ParamPosition.Query && param != null)
            {
                url = $"{url}{(param.ToString().StartsWith("?") ? string.Empty : "?")}{param}";
                isCombineParam = true;
            }

            //使用时间戳绕过CDN
            if (useRandomTimeStamp)
                url = $"{url}{(isCombineParam ? "&" : "?")}t={DateTime.Now.ToFileTime()}";


            using (var httpClient = httpClientFactory.CreateClient())
            {
                httpClient.Timeout = TimeOut;
                using (var request = new HttpRequestMessage(httpMethod, url))
                {
                    if (requestHeaders != null && requestHeaders.Count > 0)
                        foreach (var key in requestHeaders.Keys)
                            request.Headers.Add(key, requestHeaders[key]);

                    if (paramPosition == ParamPosition.Body && param != null)
                        request.Content = new StringContent(contentType == ContentType_Json ? JsonConvert.SerializeObject(param) : param.ToString(), Encoding.UTF8, contentType);

                    using (var response = httpClient.SendAsync(request, httpCompletionOption).Result)
                    {
                        if (!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.Redirect && response.StatusCode != HttpStatusCode.Moved)
                            throw new Exception($"Reuqest {url} HttpCode {response.StatusCode}");
                        return new RestApiResult()
                        {
                            StatusCode = response.StatusCode,
                            Content = httpCompletionOption == HttpCompletionOption.ResponseContentRead ? response.Content.ReadAsStringAsync().Result :
                                                                                                         string.Empty,
                            Headers = getResponseHeader ? response.Headers : null
                        };
                    }
                }
            }
        }

    }

    public class RestApiResult
    {
        public HttpStatusCode StatusCode { get; set; }

        public string Content { get; set; }

        public HttpResponseHeaders Headers { get; set; }
    }

    /// <summary>
    /// 参数传递位置
    /// </summary>
    public enum ParamPosition
    {
        Query,
        Body
    }
}