using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using WCS.Model;
using WCS.Model.ApiModel.MXBackgroundThread;

namespace 智慧物流软件系统.Api
{
    public static class ApiHelp
    {
        public static HttpClient httpClient;
        static ApiHelp()
        {
            httpClient = new HttpClient();
            httpClient.Timeout = TimeSpan.FromSeconds(10);
            httpClient.DefaultRequestHeaders.Add("UserModel-Agent", "Chrome/95.0.4638.69 Safari/537.36");
            ServicePointManager.Expect100Continue = false;
        }

        public static async Task<ResponseBase> Get(string uri, object? query = null, object? body = null)
        {
            return await Send(HttpMethod.Get, uri, query, body);
        }

        public static async Task<ResponseBase> Get(IEnumerable<object> uri, object? query = null, object? body = null)
        {
            return await Send(HttpMethod.Get, uri, query, body);
        }

        public static async Task<T> Get<T>(string uri, object? query = null, object? body = null)
        {
            return await Send<T>(HttpMethod.Get, uri, query, body);
        }

        public static async Task<T> Get<T>(IEnumerable<object> uri, object? query = null, object? body = null)
        {
            return await Send<T>(HttpMethod.Get, uri, query, body);
        }

        public static async Task<ResponseBase> Post(string uri, object? body = null, object? query = null)
        {
            return await Send(HttpMethod.Post, uri, query, body);
        }

        public static async Task<ResponseBase> Post(IEnumerable<object> uri, object? body = null, object? query = null)
        {
            return await Send(HttpMethod.Post, uri, query, body);
        }

        public static async Task<T> Post<T>(string uri, object? body = null, object? query = null)
        {
            return await Send<T>(HttpMethod.Post, uri, query, body);
        }

        public static async Task<T> Post<T>(IEnumerable<object> uri, object? body = null, object? query = null)
        {
            return await Send<T>(HttpMethod.Post, uri, query, body);
        }

        public static async Task<ResponseBase> Send(HttpMethod method, string uri, object? query = null, object? body = null)
        {
            return await Send(method, new string[] { uri }, query, body);
        }

        public static async Task<ResponseBase> Send(HttpMethod method, IEnumerable<object> uri, object? query = null, object? body = null)
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, "".AppendPathSegments(uri).SetQueryParams(query));

            if (body != null)
            {
                var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
                httpRequestMessage.Content = content;
            }

            var re = await httpClient.SendAsync(httpRequestMessage);
            if (!re.IsSuccessStatusCode)
                return new ResponseBase() { Code = (int)re.StatusCode };

            var con = await re.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<ResponseBase>(con) ?? new ResponseBase();
        }

        public static async Task<T> Send<T>(HttpMethod method, string uri, object? query = null, object? body = null)
        {
            return await Send<T>(method, new string[] { uri }, query, body);
        }

        public static async Task<T> Send<T>(HttpMethod method, IEnumerable<object> uri, object? query = null, object? body = null)
        {
            try
            {
                var url = "".AppendPathSegments(uri).SetQueryParams(query);
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url);

                if (body != null)
                {
                    var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
                    httpRequestMessage.Content = content;
                }

                var re = await httpClient.SendAsync(httpRequestMessage);
                if (!re.IsSuccessStatusCode)
                    return default(T);

                var con = await re.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<T>(con) ?? default(T); ;
            }
            catch (Exception ex)
            {
                return default(T);
            }

        }

        /// <summary>
        /// 追加路径片段（有更高要求可以使用Flurl库）
        /// </summary>
        /// <param name="url">地址，如 https://www.baidu.com</param>
        /// <param name="segments">路径片段</param>
        /// <returns>地址</returns>
        public static string AppendPathSegments(this string url, IEnumerable<object> segments)
        {
            string urlStr = url.Trim();
            foreach (var segment in segments)
            {
                var val = segment?.ToString()?.Trim() ?? "";
                if (string.IsNullOrWhiteSpace(val))
                    continue;

                if (urlStr.EndsWith("/"))
                    urlStr = urlStr.Substring(0, urlStr.Length - 1);

                if (val.Length > 0)
                    urlStr += string.IsNullOrEmpty(urlStr) || val.StartsWith("/") ? val : $"/{val}";
            }
            return urlStr;
        }

        /// <summary>
        /// 设置Query参数（有更高要求可以使用Flurl库）
        /// </summary>
        /// <param name="url">地址，如 https://www.baidu.com/s</param>
        /// <param name="values">参数，支持字典和对象</param>
        /// <returns>地址</returns>
        public static string SetQueryParams(this string url, object? values)
        {
            string urlStr = url;
            if (values == null)
                return urlStr;

            List<string> kv = new List<string>();
            if (values is IEnumerable jh)
            {
                if (jh is IDictionary dict)
                {
                    foreach (DictionaryEntry item in dict)
                        kv.Add($"{item.Key?.ToString()}={item.Value?.ToString()}");
                }
            }
            else
            {
                foreach (var item in values.GetType().GetProperties())
                {
                    if (item.CanRead)
                        kv.Add($"{item.Name}={item.GetValue(values)?.ToString()}");
                }
            }

            if (kv.Any())
            {
                if (!urlStr.Contains("?"))
                    urlStr += "?";
                else
                {
                    if (!urlStr.EndsWith("&"))
                        urlStr += "&";
                }

                urlStr += string.Join("&", kv);
            }

            return urlStr;
        }

        /// <summary>
        /// Post方式下载Excel文件
        /// </summary>
        /// <param name="localFilePath">文件保存的路径</param>
        /// <param name="method"></param>
        /// <param name="requestUrl"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static async Task PostDownloadFileAsync(string localFilePath, HttpMethod method, string requestUrl, object? body = null)
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, requestUrl);
            if (body != null)
            {
                var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
                httpRequestMessage.Content = content;
            }
            using (var response = await httpClient.SendAsync(httpRequestMessage))
            {
                response.EnsureSuccessStatusCode(); // 确保请求成功  

                // 获取内容头中的文件名（如果需要的话）  
                //var contentDisposition = ContentDispositionHeaderValue.Parse(response.Content.Headers.ContentDisposition.ToString());
                //string filename = contentDisposition.FileName.Trim('"'); // 去除引号  
                var filename = string.Empty;
                // 如果提供的本地文件路径没有文件名，则使用从响应头中获取的文件名  
                if (Path.GetFileName(localFilePath) == string.Empty)
                {
                    localFilePath = Path.Combine(Path.GetDirectoryName(localFilePath), filename);
                }
                // 写入文件  
                using (var fileStream = new FileStream(localFilePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                {
                    await response.Content.CopyToAsync(fileStream);
                }
            }
        }

        /// <summary>
        /// Post方式导入Excel文件
        /// </summary>
        /// <param name="localFilePath">文件保存的路径</param>
        /// <param name="method"></param>
        /// <param name="requestUrl"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static async Task<T> PostImportFileAsync<T>(string localFilePath, HttpMethod method, string requestUrl, string userName, string deviceType)
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, requestUrl);

            using (var content = new MultipartFormDataContent())
            {
                var fileContent = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
                fileContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(fileContent, "excelFile", Path.GetFileName(localFilePath));

                var userNameContent = new StringContent(userName);
                userNameContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(userNameContent, "userName");

                var deviceTypeContent = new StringContent(deviceType);
                deviceTypeContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(deviceTypeContent, "deviceType");

                httpRequestMessage.Content = content;
                using (var response = await httpClient.SendAsync(httpRequestMessage))
                {
                    response.EnsureSuccessStatusCode(); // 确保请求成功  
                    var filename = string.Empty;

                    if (!response.IsSuccessStatusCode)
                        return default(T);

                    var con = await response.Content.ReadAsStringAsync();
                    return JsonConvert.DeserializeObject<T>(con) ?? default(T); ;
                }
            }
        }


        public static async Task<T> StationPostImportFileAsync<T>(string localFilePath, HttpMethod method, string requestUrl, string userName, string deviceType,string stationCode)
        {
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, requestUrl);

            using (var content = new MultipartFormDataContent())
            {
                var fileContent = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
                fileContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(fileContent, "excelFile", Path.GetFileName(localFilePath));

                var userNameContent = new StringContent(userName);
                userNameContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(userNameContent, "userName");

                var deviceTypeContent = new StringContent(deviceType);
                deviceTypeContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(deviceTypeContent, "deviceType");

                var stationCodeContent = new StringContent(stationCode);
                stationCodeContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/form-data");
                content.Add(stationCodeContent, "stationCode");

                httpRequestMessage.Content = content;
                using (var response = await httpClient.SendAsync(httpRequestMessage))
                {
                    response.EnsureSuccessStatusCode(); // 确保请求成功  
                    var filename = string.Empty;

                    if (!response.IsSuccessStatusCode)
                        return default(T);

                    var con = await response.Content.ReadAsStringAsync();
                    return JsonConvert.DeserializeObject<T>(con) ?? default(T); ;
                }
            }
        }
        /// <summary>
        /// 调用接口超时时间10s
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="dataObj"></param>
        /// <param name="httpMethod"></param>
        /// <param name="isSaveLog"></param>
        /// <returns></returns>
        public static T GetDataFromHttp<T>(string url, object dataObj, string httpMethod, bool isSaveLog = false)
        {
            Guid guid = Guid.NewGuid();
            var data = dataObj == null ? string.Empty : JsonConvert.SerializeObject(dataObj);
            try
            {
                if (isSaveLog)
                    Logs.Write($"【{guid}】开始请求调用接口   url：{url}   请求方式：{httpMethod}   数据：{data}", LogsType.Api);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = httpMethod;
                request.ContentType = "application/json";
                request.Timeout = 10000;

                if (!string.IsNullOrEmpty(data))
                {
                    string strContent = data; //参数data
                    using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
                    {
                        dataStream.Write(strContent);
                        dataStream.Close();
                    }
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                string encoding = response.ContentEncoding;
                if (encoding == null || encoding.Length < 1)
                {
                    encoding = "UTF-8"; //默认编码  
                }
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
                string retString = reader.ReadToEnd();
                if (isSaveLog)
                    Logs.Write($"【{guid}】请求调用接口结束 返回数据为{retString}", LogsType.Api);
                return JsonConvert.DeserializeObject<T>(retString);
            }
            catch (Exception ex)
            {
                Logs.Write($"【{guid}】请求调用遇到异常 异常信息为{ex.Message}");
                return default(T);
            }
        }

        /// <summary>
        /// 调用接口-长延时（MX MES接口返回时间偶尔10秒+为保证业务能正常进行所以增加此接口）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="url"></param>
        /// <param name="httpMethod"></param>
        /// <param name="isSaveLog"></param>
        /// <returns></returns>
        public static ApiResult<T> MXGetDataFromHttpLongWait<T>(string data, string url, string httpMethod, bool isSaveLog = false)
        {
            Guid guid = Guid.NewGuid();
            try
            {
                if (isSaveLog)
                    Logs.Write($"【{guid}】开始请求调用接口   url：{url}   请求方式：{httpMethod}   数据：{data}");
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = httpMethod;
                request.ContentType = "application/json";
                request.Timeout = 20000;
                if (!string.IsNullOrEmpty(data))
                {
                    string strContent = data; //参数data
                    using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
                    {
                        dataStream.Write(strContent);
                        dataStream.Close();
                    }
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                string encoding = response.ContentEncoding;
                if (encoding == null || encoding.Length < 1)
                {
                    encoding = "UTF-8"; //默认编码  
                }
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
                string retString = reader.ReadToEnd();
                if (isSaveLog)
                    Logs.Write($"【{guid}】请求调用接口结束 返回数据为{retString}");
                return JsonConvert.DeserializeObject<ApiResult<T>>(retString);
            }
            catch (Exception ex)
            {
                Logs.Write($"【{guid}】请求调用遇到异常 异常信息为{ex.Message}");
                return new ApiResult<T>()
                {
                    code = 500,
                    message = ex.Message,
                };
            }
        }
        public static ApiResult<T> MXGetDataFromHttp<T>(string data, string url, string httpMethod, bool isSaveLog = false)
        {
            Guid guid = Guid.NewGuid();
            try
            {
                if (isSaveLog)
                    Logs.Write($"【{guid}】开始请求调用接口   url：{url}   请求方式：{httpMethod}   数据：{data}");
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = httpMethod;
                request.ContentType = "application/json";
                request.Timeout = 8000;
                if (!string.IsNullOrEmpty(data))
                {
                    string strContent = data; //参数data
                    using (StreamWriter dataStream = new StreamWriter(request.GetRequestStream()))
                    {
                        dataStream.Write(strContent);
                        dataStream.Close();
                    }
                }
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                string encoding = response.ContentEncoding;
                if (encoding == null || encoding.Length < 1)
                {
                    encoding = "UTF-8"; //默认编码  
                }
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
                string retString = reader.ReadToEnd();
                if (isSaveLog)
                    Logs.Write($"【{guid}】请求调用接口结束 返回数据为{retString}");
                return JsonConvert.DeserializeObject<ApiResult<T>>(retString);
            }
            catch (Exception ex)
            {
                Logs.Write($"【{guid}】请求调用遇到异常 异常信息为{ex.Message}");
                return new ApiResult<T>()
                {
                    code = 500,
                    message = ex.Message,
                };
            }
        }
    }
}
