using System.Diagnostics;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
using WmsMobileServe.Utils.HttpUtils.Entity;


namespace WmsMobileServe.Utils.HttpUtils;

public class WebApiClient
{
    /*
     * 作者：菻蔃
     *
     * 版本时间：2024年5月10日
     *
     */

    public WebApiClient() { }

    private string? _baseUrl = string.Empty;

    private Action<ApiResponseInfo>? _apiAction;

    public WebApiClient(Action<ApiResponseInfo> apiAction)
    {
        _apiAction = apiAction;
    }

    public WebApiClient(string url, Action<ApiResponseInfo> action)
    {
        _baseUrl = url;
        _apiAction = action;
    }

    /// <summary>
    /// 设置响应事件，
    /// </summary>
    /// <param name="action"></param>
    public void SetResponseAction(Action<ApiResponseInfo> action)
    {
        _apiAction = action;
    }
    public void SetBaseUrl(string url)
    {
        _baseUrl = url;
    }

    /// <summary>
    /// 执行POST请求
    /// </summary>
    /// <typeparam name="TRequest"></typeparam>
    /// <typeparam name="TResponse"></typeparam>
    /// <param name="requestEntity"></param>
    /// <param name="method"></param>
    /// <param name="time"></param>
    /// <returns></returns>
    public ApiResponseInfo<TResponse> HttpPost<TRequest, TResponse>(TRequest requestEntity, string method = "", int time = 10000, bool executeAction = true) where TRequest : class where TResponse : class, new()
    {
        ApiResponseInfo<TResponse> result = new()
        {
            RequestMethod = "POST"
        };
        string address = _baseUrl + method;
        Encoding encoding = Encoding.UTF8;
        Stopwatch sw = new();
        string sendMes = JsonConvert.SerializeObject(requestEntity);
        sw.Start();
        try
        {
            HttpContent content = new StringContent(sendMes, encoding, "application/json");
            HttpClient client = new();
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.Timeout = new TimeSpan(0, 0, 0, 0, time);
            result.RequestTime = DateTime.Now;
            var requestTask = client.PostAsync(address, content);
            requestTask.Wait();
            var responseResult = requestTask.Result;
            if (responseResult.IsSuccessStatusCode)
            {
                var responseRead = responseResult.Content.ReadAsStringAsync();
                responseRead.Wait();
                string responseString = responseRead.Result;
                result.IsSend = true;
                result.RequestMsg = sendMes;
                result.RequestUrl = address;
                result.ResponseMsg = responseString;
                result.ResponseEntity = JsonConvert.DeserializeObject<TResponse>(responseString);
            }
            else
            {
                var responseCode = responseResult.StatusCode;
                var responseRead = responseResult.Content.ReadAsStringAsync();
                responseRead.Wait();
                string responseString = responseRead.Result;
                result.IsSend = false;
                result.RequestMsg = sendMes;
                result.RequestUrl = address;
                result.Exception = new Exception($"[{responseCode}]{responseString}");
            }
        }
        catch (Exception ex)
        {
            result.IsSend = false;
            result.RequestMsg = sendMes;
            result.RequestUrl = address;
            result.Exception = ex;
        }
        result.ResponseTime = DateTime.Now;
        sw.Stop();
        result.ResponseTime = DateTime.Now;
        TimeSpan ts = sw.Elapsed;
        result.UseTime = ts.TotalMilliseconds;
        if (executeAction)
        {
            _apiAction?.Invoke(result);
        }
        return result;
    }


    public ApiResponseInfo HttpGet(Dictionary<string, object>? request, string method = "", int time = 10000, bool executeAction = true)
    {
        ApiResponseInfo result = new()
        {
            RequestMethod = "GET"
        };
        Encoding encoding = Encoding.UTF8;
        string paramString = "";
        if (request != null)
        {
            foreach (var param in request)
            {
                paramString += $"{param.Key}={param.Value}";
            }
        }
        string url = _baseUrl + method + $"{(string.IsNullOrEmpty(paramString) ? "" : $"?{paramString}")}";
        Stopwatch sw = new();
        sw.Start();
        try
        {
            HttpClient client = new();
            client.Timeout = new TimeSpan(0, 0, 0, 0, time);
            result.RequestTime = DateTime.Now;
            var requestTask = client.GetAsync(url);
            requestTask.Wait();
            var responseResult = requestTask.Result;
            if (responseResult.IsSuccessStatusCode)
            {
                var responseRead = responseResult.Content.ReadAsStringAsync();
                responseRead.Wait();
                string responseString = responseRead.Result;
                result.IsSend = true;
                result.RequestMsg = paramString;
                result.RequestUrl = url;
                result.ResponseMsg = responseString;
            }
            else
            {
                var responseCode = responseResult.StatusCode;
                var responseRead = responseResult.Content.ReadAsStringAsync();
                responseRead.Wait();
                string responseString = responseRead.Result;
                result.IsSend = false;
                result.RequestMsg = paramString;
                result.RequestUrl = url;
                result.Exception = new Exception($"[{responseCode}]{responseString}");
            }
        }
        catch (Exception ex)
        {
            result.IsSend = false;
            result.RequestMsg = paramString;
            result.RequestUrl = url;
            result.Exception = ex;
        }
        result.ResponseTime = DateTime.Now;
        sw.Stop();
        result.ResponseTime = DateTime.Now;
        TimeSpan ts = sw.Elapsed;
        result.UseTime = ts.TotalMilliseconds;
        if (executeAction)
        {
            _apiAction?.Invoke(result);
        }
        return result;
    }


}