using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Channels;
using System.Threading.Tasks;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.MpsOrder;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;

namespace XYY.Service.Standard.ChannelApi.YuanPeng
{
    public class Api : IBaseApi
    {
        public string ServiceName => "YuanPeng";
        public Api() { }
        public void CannelOrders(List<string> systemNO)
        {
            throw new NotImplementedException();
        }
        public async Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        { throw new NotImplementedException(); }
        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }
        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        public async 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 ConvertToRequest(order, channel, arg.Order);
            string json = JsonConvert.SerializeObject(post);
            RestClient client = new RestClient(channel.ApiHost + "/open-api/order/create");
            client.Timeout = -1;//超时设置
            client.RemoteCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<BasicResult<DataUploadResult>>(response.Content);
                if (result.success)
                {
                    throw new Exception("由于渠道的特殊性，请等待30-40秒之后重新操作下单， 最好等待1分钟！");
                }
                else
                {
                    if (result.message.Contains("已存在"))
                    {
                        return await GetOrderInfo(order, channel, arg);
                    }
                    throw new Exception($"YuanPeng下单失败:{result.message}");
                }
            }
            else
            {
                throw new Exception($"YuanPeng下单异常:{response.ErrorMessage?? response.Content}");
            }
        }
        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            var post = new PdfLabelRequest() { apiToken = channel.ApiSecret, orderNo = result.ServiceOrderNumber };
            string json = JsonConvert.SerializeObject(post);
            RestClient client = new RestClient(channel.ApiHost + "/open-api/order/label");
            client.RemoteCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
            client.Timeout = -1;//超时设置
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var pdfResult = JsonConvert.DeserializeObject<BasicResult<PdfLabelResult>>(response.Content);
                if (pdfResult.success)
                {
                    WebClient webClient = new WebClient();
                    var data = webClient.DownloadData(pdfResult.result.url);
                    return data;
                }
                else
                {
                    throw new Exception($"YuanPeng获取面单失败:{pdfResult.message}");
                }
            }
            else
            {
                throw new Exception($"YuanPeng获取面单异常:{response.Content ?? response.ErrorMessage}");
            }
        }
        private async Task<DataUploadRequest> ConvertToRequest(Order_Order order, Logistics_Channel channel, Order_MpsOrder mpsOrder)
        {
            if (order.ReceiverStreet.Length > 105) { throw new Exception("渠道YP收件人地址最大长度为105个字符！"); }
            var stree = SubstringStreet(order.ReceiverStreet);
            var sendStree = SubstringStreet(channel.SenderStreet);
            DataUploadRequest dataUploadRequest = new DataUploadRequest()
            {
                apiToken = channel.ApiSecret,
                productCode = channel.ServiceChannelCode,
                customerNo = order.CustomerOrderNo,
                orderWeight = mpsOrder.Boxs.Sum(x => x.OpInputWeight),
                currencyCode = mpsOrder.Boxs[0].Goods[0].Currency,//只取第一条
            };
            dataUploadRequest.consigneeShipper = new ConsigneeShipper()
            {
                consigneeName = order.ReceiverName,
                consigneeCompanyName = order.ReceiverCompany,
                consigneeCountryCode = order.ReceiverCountryCode,
                consigneeStateOrProvince = order.ReceiverState,
                consigneeCity = order.ReceiverCity,
                consigneeAddress1 = stree[0],
                consigneeAddress2 = stree.Count > 1 ? stree[1] : "",
                consigneeAddress3 = stree.Count > 2 ? stree[2] : "",
                consigneePostCode = order.ReceiverZipCode,
                consigneePhone = order.ReceiverPhone,
                consigneeEmail = order.ReceiverEmail,
                consigneeHouseNumber = order.House,

                shipperName = channel.SenderName,
                shipperCompanyName = channel.SenderCompany,
                shipperCountryCode = channel.SenderCountryCode,
                shipperStateOrProvince = channel.SenderState,
                shipperCity = channel.SenderCity,
                shipperAddress1 = sendStree[0],
                shipperAddress2 = sendStree.Count > 1 ? sendStree[1] : "",
                shipperAddress3 = sendStree.Count > 2 ? sendStree[2] : "",
                shipperPostCode = channel.SenderZipCode,
                shipperPhone = channel.SenderPhone,
                shipperEmail = channel.SenderEmail,
            };
            dataUploadRequest.boxList = new List<BoxListItem>();
            dataUploadRequest.goodsList = new List<GoodsListItem>();
            foreach (var box in mpsOrder.Boxs)
            {
                BoxListItem listItem = new BoxListItem()
                {
                    boxNo = box.BoxNumber,
                    boxWeight = (double)box.OpInputWeight,
                    boxLength = (int)box.OpLength,
                    boxWidth = (int)box.OpWidth,
                    boxHeight = (int)box.OpHeight,
                };
                dataUploadRequest.boxList.Add(listItem);
                foreach (var good in box.Goods)
                {
                    GoodsListItem goodsListItem = new GoodsListItem()
                    {
                        goodsName = good.CnName,
                        goodsNameEn = good.EnName,
                        quantity = good.Quantity,
                        value = good.Quantity * good.GoodsValue,
                        weight = Convert.ToDouble(good.Quantity * good.Weight),
                        hsCode = good.HsCode,
                        boxNo = box.BoxNumber,
                    };
                    dataUploadRequest.goodsList.Add(goodsListItem);
                }
            }
            return dataUploadRequest;
        }
        private async Task<Dictionary<string, string>> GetBoxServerNo(Logistics_Channel channel, ExtendArg arg, string channelOrderNo)
        {
            var body = new PdfLabelRequest() { apiToken = channel.ApiSecret, orderNo = channelOrderNo };
            string boxJson = JsonConvert.SerializeObject(body);
            RestClient boxClient = new RestClient(channel.ApiHost + "/open-api/order/getTrackingNumber");
            boxClient.RemoteCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
            RestRequest boxRequest = new RestRequest(Method.POST);
            boxRequest.AddHeader("Content-Type", "application/json");
            boxRequest.AddParameter("application/json", boxJson, ParameterType.RequestBody);
            var boxResponse = boxClient.Execute(boxRequest);
            if (boxResponse.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var boxResult = JsonConvert.DeserializeObject<BasicResult<List<BoxNoResult>>>(boxResponse.Content);
                if (boxResult.success)
                {
                    return boxResult.result.ToDictionary(x => arg.Order.Boxs.Where(y => y.BoxNumber == x.boxNo).FirstOrDefault().BoxServiceNumber, x => x.serverNo);
                }
            }
            return new Dictionary<string, string>();
        }
        private async Task<UploadResult> GetOrderInfo(Order_Order order, Logistics_Channel channel, ExtendArg arg)
        {
            var post = new PdfLabelRequest() { apiToken = channel.ApiSecret, orderNo = order.CustomerOrderNo};
            string json = JsonConvert.SerializeObject(post);
            RestClient client = new RestClient(channel.ApiHost + "/open-api/order/info");
            client.RemoteCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
            RestRequest request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<BasicResult<DataUploadResult>>(response.Content);
                if (result.success)
                {
                    var uploadResult = new UploadResult
                    {
                        IsSuccess = true,
                        MPSTrackings = await GetBoxServerNo(channel, arg, order.CustomerOrderNo),
                        ServiceOrderNumber = result.result.orderNo,
                        TrackingNumber = result.result.serverNo,
                    };
                    //获取单号
                    return uploadResult;
                }
                else
                {
                    throw new Exception($"YuanPeng下单失败:{result.message}");
                }

            }
            else
            {
                throw new Exception($"YuanPeng获取订单信息异常:{response.Content ?? response.ErrorMessage}");
            }
        }
        private List<string> SubstringStreet(string ReceiverStreet)
        {
            List<string> address = new List<string>() { };
            string tempstring = string.Empty;
            if (ReceiverStreet.Length <= 35) { address.Add(ReceiverStreet); return address; }

            if (ReceiverStreet.Length > 35) { address.Add(ReceiverStreet.Substring(0, 35)); tempstring = ReceiverStreet.Substring(35, ReceiverStreet.Length - 35); }
            if (tempstring.Length > 35) { address.Add(tempstring.Substring(0, 35)); tempstring = tempstring.Substring(35, tempstring.Length - 35); }
            if (tempstring.Length <= 35) { address.Add(tempstring); }
            return address;
        }
    }
}
