using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;

namespace XYY.Service.Standard.ChannelApi.PitneyBowes
{
    public partial class Api : IBaseApi
    {
        public string ServiceName => "PitneyBowes";

        public string CLIENT_ID = "3407";
        public string CLIENT_FACILITY_ID = "2661";
        public string SHIPPER_ID = "3002802839";
        public Task<List<BagDeclareErrosResult>> BagDeclare(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 string GetCARRIER_FACILITY_ID(Logistics_Channel channel)
        {
            if (channel.PublicCode.EndsWith("-D"))
            {
                channel.PublicCode=channel.PublicCode.Replace("-D", "");
            }
            string CARRIER_FACILITY_ID = "";
            switch (channel.PublicCode)
            {
                case "X-PB-LAX":
                    CARRIER_FACILITY_ID = "1787";
                    break;
                case "X-PB-JFK":
                    CARRIER_FACILITY_ID = "1779";
                    break;
                case "X-PB-ORD":
                    CARRIER_FACILITY_ID = "2692";
                    break;
            }
            return CARRIER_FACILITY_ID;
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            string url = "https://shipping-api.pitneybowes.com/shippingservices/v1/shipments";
            string token = getToken(channel);
            var request = new OrderRequest();
            SetFromAddress(order, channel, request);
            SetToAddress(order, request);
            request.shipmentOptions = new List<OptionsItem> { };

            if (order.Width == 0)
            {
                order.Width = 0.64m;
            }
            if (order.Height == 0)
            {
                order.Height = 7.62m;
            }
            if (order.Length == 0)
            {
                order.Length = 15.24m;
            }

            string serviceId = "";
            string NON_DELIVERY_OPTION = "";
            if (order.CustomerWeight < 454)
            {
                serviceId = "PSLW";
                NON_DELIVERY_OPTION = "";
            }
            else
            {
                serviceId = "PRCLSEL";
                NON_DELIVERY_OPTION = "ChangeServiceRequested";
            }

            string CARRIER_FACILITY_ID = GetCARRIER_FACILITY_ID(channel);


            request.parcel = new Parcel
            {
                weight = new Weight { unitOfMeasurement = "GM", weight = (order.CustomerWeight).ToString() },
                dimension = new Dimension { width = order.Width.ToString(), height = order.Height.ToString(), length = order.Length.ToString(), unitOfMeasurement = "CM" }
            };
            request.documents = new List<DocumentsItem>
            {
                new DocumentsItem
                {
                    contentType = "URL", fileFormat = "PDF", size = "DOC_4X6", type = "SHIPPING_LABEL"
                }
            };
            request.rates = new List<RatesItem>
            {
                new RatesItem {
                    specialServices = new List<SpecialServicesItem> {
                        new SpecialServicesItem {
                            specialServiceId= "DelCon"
                        }
                    }
                    ,
                    carrier = "PBCS", serviceId = serviceId, parcelType = "PKG"
                }
            };
            request.shipmentOptions = new List<OptionsItem> {
                new OptionsItem { name = "CLIENT_FACILITY_ID", value =CLIENT_FACILITY_ID},
                new OptionsItem{name="CARRIER_FACILITY_ID",value=CARRIER_FACILITY_ID},
                new OptionsItem{name="CLIENT_ID",value=CLIENT_ID},
                new OptionsItem{name="SHIPPER_ID",value=SHIPPER_ID},
                new OptionsItem { name = "MINIMAL_ADDRESS_VALIDATION", value = "true" },
                new OptionsItem{ name="NON_DELIVERY_OPTION",value=NON_DELIVERY_OPTION }
            };

            var response = await SendData<OrderRequest, OrderResult>(request, channel, url);

            return new UploadResult
            {
                TrackingNumber = response.parcelTrackingNumber,
                ServiceOrderNumber = response.shipmentId,
                DownloadUrl = response.documents[0].contents,
                IsSuccess = true
            };
        }

        /// <summary>
        /// POST Manifest
        /// </summary>
        /// <returns></returns>
        public async Task<ManifestResult> Manifest(Logistics_Channel channel)
        {
            string url = " https://shipping-api.pitneybowes.com/shippingservices/v1/manifests";
            ManifestRequset requset = new ManifestRequset
            {
                carrier = "Newgistics",
                submissionDate = DateTime.Now.ToUniversalTime().ToString_yyyyMMdd(),
                parameters = new List<OptionsItem>
                {
                    new OptionsItem{name = "SHIPPER_ID",value=SHIPPER_ID
                    },
                    new OptionsItem
                    {
                        name="CLIENT_ID",
                        value=CLIENT_ID
                    }
                }
            };
            var result = await SendData<ManifestRequset, ManifestResult>(requset, channel, url);
            return result;
        }

        public class ManifestResult
        {

            /// <summary>
            /// 
            /// </summary>
            public string carrier { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string submissionDate { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public List<OptionsItem> parameters { get; set; }
            public string manifestId { get; set; }
        }

        public class ManifestRequset
        {
            /// <summary>
            /// 
            /// </summary>
            public string carrier { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string submissionDate { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public List<OptionsItem> parameters { get; set; }
        }

        public async Task<T2> SendData<T1, T2>(T1 t, Logistics_Channel channel, string action)
        {
            string url = action;
            string token = getToken(channel);
            System.Net.WebClient client = new System.Net.WebClient();
            client.Headers.Add("Authorization", "Bearer " + token);
            client.Headers.Add("Content-Type", "application/json");
            client.Headers.Add("X-PB-TransactionId", DateTime.Now.ToString("yyyyMMddHHmmssfff"));
            client.Headers.Add("X-PB-UnifiedErrorStructure", "true");
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(t);
            try
            {
                string d = await client.UploadStringTaskAsync(new Uri(url), json);
                try
                {
                    return Newtonsoft.Json.JsonConvert.DeserializeObject<T2>(d);
                }
                catch (Exception ex)
                {
                    throw new Exception("解析返回结果失败" + d + " " + ex.Message);
                }
            }
            catch (System.Net.WebException ex)
            {
                string d = new System.IO.StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
                throw new Exception(d);
            }

        }


        public class ContainerManifestResultData
        {
            /// <summary>
            /// 
            /// </summary>
            public string pbContainerId { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string labelData { get; set; }
        }

        public class ContainerManifestResult
        {
            /// <summary>
            /// 
            /// </summary>
            public ContainerManifestResultData data { get; set; }
        }


        /// <summary>
        /// 大包标签
        /// </summary>
        /// <param name="boxNumber"></param>
        /// <param name="channel"></param>
        /// <param name="details"></param>
        /// <returns></returns>
        public async Task<ContainerManifestResultData> ContainerManifest(string boxNumber, string port, Logistics_Channel channel, List<string> details)
        {


            string url = "https://shipping-api.pitneybowes.com/shippingservices//v1/container-manifest";
            ContainerManifestRoot root = new ContainerManifestRoot();
            root.carrier = "Newgistics";
            root.containerType = "Carton";
            root.parcelTrackingNumbers = details;
            root.documents = new List<DocumentsItem> { new DocumentsItem { fileFormat = "PDF", size = "DOC_4X4", contentType = "URL" } };


            string CARRIER_GATEWAY_FACILITY_ID = GetCARRIER_FACILITY_ID(channel);
            if (CARRIER_GATEWAY_FACILITY_ID == "1787")
            {
                CARRIER_GATEWAY_FACILITY_ID = "1304";
            }

            string FACILITY_ID = CARRIER_GATEWAY_FACILITY_ID;

            //ORD的我们二次划分
            if (!string.IsNullOrEmpty(port))
            {
                if (channel.PublicCode == "X-PB-ORD")
                {
                    if (port == "DFW")
                    {
                        FACILITY_ID = "2433";
                    }
                    else if (port == "IND")
                    {
                        FACILITY_ID = "1585";
                    }
                    else if (port == "ORD" || string.IsNullOrEmpty(port))
                    {
                        FACILITY_ID = "2692";
                    }
                }
            }

            root.parameters = new List<OptionsItem>
            {
                new OptionsItem
                {
                    name = "CARRIER_FACILITY_ID",
                    value = FACILITY_ID
                },
                new OptionsItem
                {
                    name = "CARRIER_GATEWAY_FACILITY_ID",
                    value=CARRIER_GATEWAY_FACILITY_ID
                },
                new OptionsItem
                {
                    name="CLIENT_ID",
                    value=CLIENT_ID
                },
                new OptionsItem
                {
                    name = "SHIP_DATE",
                    value=DateTime.Now.ToUniversalTime().ToString_yyyyMMdd()
                },
                new OptionsItem
                {
                    name = "ESTIMATED_ARRIVAL_DATE",
                    value=DateTime.Now.AddDays(5).ToUniversalTime().ToString_yyyyMMdd()
                },
                new OptionsItem
                {
                    name="PRINT_CUSTOM_MESSAGE_1",
                    value = boxNumber
                }
            };
            var result = await SendData<ContainerManifestRoot, ContainerManifestResult>(root, channel, url);
            return result.data;

        }

        private static void SetToAddress(Order_Order order, OrderRequest request)
        {
            request.toAddress = new Address
            {
                cityTown = order.ReceiverCity,
                company = order.ReceiverCompany,
                countryCode = order.ReceiverCountryCode,
                postalCode = order.ReceiverZipCode,
                addressLines = new List<string> { order.ReceiverStreet },
                name = order.ReceiverName,
                stateProvince = order.ReceiverState,
                residential = "true",
            };
        }

        private static void SetFromAddress(Order_Order order, Logistics_Channel channel, OrderRequest request)
        {
            request.fromAddress = new Address();
            request.fromAddress.name = channel.SenderName;
            request.fromAddress.countryCode = channel.SenderCountryCode;
            request.fromAddress.stateProvince = channel.SenderState;
            request.fromAddress.postalCode = channel.SenderZipCode;
            request.fromAddress.cityTown = channel.SenderCity;
            request.fromAddress.addressLines = new List<string> { channel.SenderStreet };
        }

        //如果好用，请收藏地址，帮忙分享。
        public class pbaccess_token
        {
            /// <summary>
            /// 
            /// </summary>
            public string access_token { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string tokenType { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string issuedAt { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string expiresIn { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string clientID { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string org { get; set; }
        }

        private string getToken(Logistics_Channel channel)
        {
            //测试帐号
            channel.ApiKey = "P8N00Pol3LYFPxAL9Ikm7g4vVR3UTa6g:BN9SmBGjZAq44s8d";
            string base64 = "UDhOMDBQb2wzTFlGUHhBTDlJa203ZzR2VlIzVVRhNmc6Qk45U21CR2paQXE0NHM4ZA==";
            //正式帐号
            channel.ApiKey = "J3X6XgkrGEZh9YX8IgIYfTNBAtAc0aoW:Wv6ijo5gRpARwIZG";
            base64 = "SjNYNlhna3JHRVpoOVlYOElnSVlmVE5CQXRBYzBhb1c6V3Y2aWpvNWdScEFSd0laRw==";
            //测试url
            string url = @"https://shipping-api-sandbox.pitneybowes.com/oauth/token";
            //正式url
            url = @"https://shipping-api.pitneybowes.com/oauth/token";

            System.Net.WebClient client = new System.Net.WebClient();
            client.Headers.Add("Authorization", "Basic " + base64);
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            var value = new System.Collections.Specialized.NameValueCollection();
            value.Add("grant_type", "client_credentials");
            byte[] data = client.UploadValues(url, value);
            var v = System.Text.UTF8Encoding.UTF8.GetString(data);
            var token = Newtonsoft.Json.JsonConvert.DeserializeObject<pbaccess_token>(v);
            return token.access_token;
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            return new System.Net.WebClient().DownloadData(result.DownloadUrl);
            return Convert.FromBase64String(result.DownloadUrl);
        }

        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }

        //获取跟踪信息
        public async Task<string> GetTracking(string trackingNumber, Logistics_Channel channel)
        {
            string url = $@"https://shipping-api.pitneybowes.com/shippingservices/v1/tracking/{trackingNumber}?packageIdentifierType=TrackingNumber";
            string token = getToken(channel);
            System.Net.WebClient client = new System.Net.WebClient();
            client.Headers.Add("Authorization", "Bearer " + token);
            string json = client.DownloadString(url);
            return json;
        }
    }
}
