using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Service.Standard.ChannelApi.HuoYing;
using XYY.Service.Standard.ChannelApi.SSG_USPS;

namespace XYY.Service.Standard.ChannelApi.DiTuo
{
    public partial class Api : IBaseApi
    {
        #region 构造
        public string ServiceName => "dituo";
        const string tokenCacheKey = "@@DITUO_TOKEN_CACHE_KEY";
        private readonly IDistributedCache _distributedCache;
        private static readonly object syncRoot = new object();
        private readonly ILogger<Api> _logger;
        public Api(IDistributedCache distributedCache, ILogger<Api> logger)
        {
            _distributedCache = distributedCache;
            _logger = logger;
        }
        #endregion
        public Task<List<Base.BagDeclareErrosResult>> BagDeclare(Model.Standard.Order.BagDeclareRequest bagDeclareRequest)
        {
            throw new NotImplementedException();
        }

        public void CannelOrders(List<string> systemNO)
        {
            throw new NotImplementedException();
        }

        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }

        public Task<List<string>> Confims(List<OrderConfimRequest> order, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            var post = await ConvertOrder(order, goods, channel, arg);
            string json = JsonConvert.SerializeObject(post);
            RestClient client = new RestClient(channel.ApiHost + "/api/svc/createOrder");
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("Authorization", GetToken(channel.ApiHost, channel.ApiKey, channel.ApiSecret));
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                DataUploadResult result = new DataUploadResult();
                var BaseResult = JsonConvert.DeserializeObject<BaseResult>(response.Content);
                if (BaseResult.code == 200)
                {
                    throw new Exception("由于渠道的特殊性，请等待30-40秒之后重新操作下单， 最好等待1分钟！");
                    //var pdf = await getLabel(channel,result.result.order_code);
                    //_logger.LogError("DiTuo下单成功:{@Response}", result);
                    //var firstPdf = pdf.result.labels.Where(x => !string.IsNullOrEmpty(x.label_url)).FirstOrDefault();
                    //var uploadResult = new UploadResult
                    //{
                    //    DownloadUrl = firstPdf.label_url,
                    //    IsSuccess = true,
                    //    MPSTrackings = new Dictionary<string, string>(),
                    //    TrackingNumber=firstPdf.tracking_number,
                    //    ServiceOrderNumber2 = result.result.order_code,
                    //};
                    //for (int i = 0; i < pdf.result.labels.Count; i++)
                    //{
                    //    uploadResult.MPSTrackings.Add(arg.Order.Boxs[i].BoxServiceNumber, pdf.result.labels[i].tracking_number);
                    //}
                    //return uploadResult;
                }
                else
                {
                    if (BaseResult.msg.Contains("请勿重复提交"))
                    {
                        result = JsonConvert.DeserializeObject<DataUploadResult>(response.Content);
                        var pdf = await getLabel(channel, result.result.order_code);
                        var firstPdf = pdf.result.labels.Where(x => !string.IsNullOrEmpty(x.label_url)).FirstOrDefault();
                        var uploadResult = new UploadResult
                        {
                            DownloadUrl = firstPdf.label_url,
                            IsSuccess = true,
                            MPSTrackings = new Dictionary<string, string>(),
                            TrackingNumber = firstPdf.tracking_number,
                            ServiceOrderNumber2 = result.result.order_code,
                        };
                        for (int i = 0; i < pdf.result.labels.Count; i++)
                        {
                            uploadResult.MPSTrackings.Add(arg.Order.Boxs[i].BoxServiceNumber, pdf.result.labels[i].tracking_number);
                        }
                        return uploadResult;
                    }
                    throw new Exception($"DiTuo下单失败:{BaseResult.msg}");
                }
            }
            else
            {
                throw new Exception($"DiTuo下单失败:{response.Content ?? response.ErrorMessage}");
            }
        }

        public async Task<byte[]> DrawPdfLabel(Base.UploadResult result, Model.Standard.Channel.Logistics_Channel channel, Model.Standard.Order.Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            WebClient client = new WebClient();
            return client.DownloadData(result.DownloadUrl);
        }
        public async Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 获取token
        /// 2小时过期
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        private string GetToken(string ApiHost, string ApiKey, string ApiSecret)
        {
            string token = _distributedCache.GetString(tokenCacheKey);

            if (!string.IsNullOrWhiteSpace(token))
            {
                return token;
            }
            else
            {
                lock (syncRoot)
                {
                    token = _distributedCache.GetString(tokenCacheKey);
                    if (!string.IsNullOrWhiteSpace(token))
                    {
                        return token;
                    }
                    else
                    {
                        var tokenInfo = GetTokenFromApi(ApiHost, ApiKey, ApiSecret);
                        token = tokenInfo.result.access_token;
                        var cacheOpt = new DistributedCacheEntryOptions
                        {
                            AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(20)
                        };
                        _distributedCache.SetStringAsync(tokenCacheKey, token, cacheOpt);
                        return token;
                    }
                }
            }
        }
        private TokenModel GetTokenFromApi(string ApiHost, string ApiKey, string ApiSecret)
        {
            var client = new RestClient($"{ApiHost}/api/svc/getToken");
            RequestTokenModel requestTokenModel = new RequestTokenModel() { app_key = ApiKey, app_token = ApiSecret };
            client.Timeout = -1;
            var request = new RestRequest(Method.POST);
            request.AddJsonBody(requestTokenModel);
            IRestResponse response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<TokenModel>(response.Content);
                if (result.code != 200)
                {
                    throw new Exception("SSGUSPS，获取授权失败！" + result.msg);
                }
                else { return result; }
            }
            else
            {
                throw new Exception("SSGUSPS，获取授权失败！" + response.Content ?? response.ErrorMessage);
            }
        }
        private async Task<DataUploadRequest> ConvertOrder(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            string firstPart = string.Empty;
            string secondPart = string.Empty;
            if (order.ReceiverStreet.Length > 34)
            {
                firstPart = order.ReceiverStreet.Substring(0, 34);
                secondPart = order.ReceiverStreet.Substring(34);
            }
            else
            {
                firstPart = order.ReceiverStreet;
            }

            DataUploadRequest post = new DataUploadRequest()
            {
                reference_no = order.CustomerOrderNo,
                sm_code = channel.ServiceChannelCode,

                oa_firstname = order.ReceiverName,
                oa_company = order.ReceiverCompany,
                oa_street_address1 = firstPart,
                oa_street_address2 = secondPart,
                oa_postcode = order.ReceiverZipCode,
                oa_state = order.ReceiverState,
                oa_city = order.ReceiverCity,
                oa_country = order.ReceiverCountryCode,
                oa_telphone = order.ReceiverPhone,

                //已确认不填发件地址，在渠道那边设置
                //shipper_address   //发件人信息，当该字段为空时，API接口的订单默认系统设置的发货地址发货；如果传了发件地址，则该地址要先进行备案否则会提示分区方案或者价格不存在
            };
            post.box_list = new List<Box_listItem>();
            foreach (var item in arg.Order.Boxs)
            {
                Box_listItem box = new Box_listItem();
                box.box_length = item.OpLength;
                box.box_width = item.OpWidth;
                box.box_height = item.OpHeight;
                box.box_actual_weight = item.OpInputWeight;
                box.customer_box_code = item.BoxNumber;
                post.box_list.Add(box);
            }
            return post;
        }
        private async Task<PdfLabelResult> getLabel(Logistics_Channel channel, string ServiceOrderNumber2)
        {
            RequestPdfLabel requestPdfLabel = new RequestPdfLabel() { order_code = ServiceOrderNumber2 };
            var json = JsonConvert.SerializeObject(requestPdfLabel);
            RestClient client = new RestClient(channel.ApiHost + "/api/svc/getLabel");
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("Authorization", GetToken(channel.ApiHost, channel.ApiKey, channel.ApiSecret));
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var pdfResult = JsonConvert.DeserializeObject<PdfLabelResult>(response.Content);
                if (pdfResult.code == 200)
                {
                    return pdfResult;
                }
                else
                {
                    if (pdfResult.code == 202)
                    {
                        throw new Exception($"DiTuo 面单获取失败:{pdfResult.msg + "|" + pdfResult.result.logistics_err}");
                    }
                    else { throw new Exception($"DiTuo 面单获取失败:{pdfResult.msg}"); }
                }
            }
            else
            {
                throw new Exception($"DiTuo面单获取失败:{response.Content ?? response.ErrorMessage}");
            }
        }
    }
}
