using System.IO;
using System.Net;
using RestSharp;
using _4PXOrder;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using System.Xml.Serialization;
using System.ServiceModel;

namespace XYY.Service.Standard.ChannelApi._4PX
{
    public class Api : IBaseApi
    {
        public string ServiceName => "4px";

        public Task<List<string>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {
            throw new NotImplementedException();
        }

        public Task<List<string>> Confims(string[] orderNo)
        {
            throw new NotImplementedException();
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            List<declareInvoice> declare = new List<declareInvoice>();
            var _details = from m in goods
                           group m by new { m.CnName, m.HsCode, m.EnName } into g
                           select new
                           {
                               HsCode = g.Key.HsCode,
                               HsEnName = g.Key.CnName,
                               HsCnName = g.Key.EnName,
                               //递四方的申报价值是按照DeclaredValue * Quantity得出来的，因此这里不能用g.Sum(),只能用g.Average()
                               DeclaredValue = g.Average(c => c.DeclareFee),
                               Quantity = g.Count()
                           };
            foreach (var item in _details)
            {
                declare.Add(new declareInvoice()
                {
                    cName = item.HsCnName,
                    declareNote = "",
                    declarePieces = item.Quantity.ToString(),
                    declareUnitCode = "PCE",
                    eName = item.HsEnName,
                    hsCode = item.HsCode,
                    unitPrice = item.DeclaredValue.ToString("F2")
                });
            }
             
            OrderOnlineServiceClient client = new OrderOnlineServiceClient();         
            
            var response = await client.createAndPreAlertOrderServiceNewAsync("46154A5A6AB4771B9BF5567544B8AA14"
                , new createAndPreAlertOrderRequest[]
             {
                    new createAndPreAlertOrderRequest()
                {
                    //货物类型：包裹(P)
                    cargoCode = "P",
                    //目的国家2字代码
                    destinationCountryCode = order.ReceiverCountryCode,
                    //发出国家2字代码
                    initialCountryCode = "CN",
                    //是否带电(Y/N)
                    hasBattery = "N",
                    //1 是礼品 2 是文件 3是商品货样 5是其他
                    mctCode = "5",
                    //是否需要POD(凭证or客户签名)
                    needPOD = "N",
                    //订单编号（包裹号）
                    orderNo = order.SystemNo,
                    //订单备注
                    orderNote = order.SystemNo,
                    //付款方式 P:预付 C:到付
                    paymentCode = "P",
                    //商品件数
                    pieces = goods.Sum(x=>x.Quantity).ToString(),
                    //对接类型
                    //prealertintegrationtype = "api对接",
                    //渠道（GP:美国联邮通挂号 ED:泛欧挂号 A6:德国联邮通挂号 FT:英国联邮通挂号 IT:新加坡小包挂号）
                      productCode = "O5",
                    //小包退件标识 Y:发件人要求退回 N:无需退回
                    returnSign = "N",
                    //发件地址
                    shipperAddress = channel.SenderStreet,
                    //发件公司（默认为站点名称）
                    shipperCompanyName =channel.SenderName,
                    //发件人
                    shipperName = channel.SenderName,
                    //发件邮编
                    shipperPostCode = channel.SenderZipCode,
                    //发件省份
                    shipperStateOrProvince = channel.SenderState,
                    //发件城市
                    shipperCity = channel.SenderCity,
                    //发件人电话
                    shipperTelephone = channel.SenderPhone,
                    
                    //收件人
                    consigneeName = order.ReceiverName,
                    //收件邮编
                    consigneePostCode =order.ReceiverZipCode,
                    //收件人省份 
                    stateOrProvince = order.ReceiverState,
                    //收件城市
                    city = order.ReceiverCity,
                    //收件人电话
                    consigneeTelephone = order.ReceiverPhone,
                    //收件人详细地址
                    street =order.ReceiverStreet,
                    //申报信息
                    declareInvoice =  declare.ToArray(),
                    customerWeight = (order.CustomerWeight/1000m).ToString()
                }
             });

            var result = response.@return.FirstOrDefault();
            if (result.ack.ToLower() == "failure")
            {
                throw new Exception(result.errors.Select(x => x.cnAction) + string.Join("。", result.errors.Select(x => x.cnMessage)));
            }
            //获取面单pdf地址
            string labelUrl = GetPdfLableUrl("46154A5A6AB4771B9BF5567544B8AA14", result.trackingNumber, "http://aeapi.4px.com/label/printOrder");
            //下载面单

            return new UploadResult()
            {
                IsSuccess = true,
                TrackingNumber = result.trackingNumber,
                DownloadUrl = labelUrl
            };
        }

        public T XmlDeserialize<T>(string s, Encoding encoding)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentNullException("s");
            if (encoding == null)
                throw new ArgumentNullException("encoding");
            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s)))
            {
                using (StreamReader sr = new StreamReader(ms, encoding))
                {
                    return (T)mySerializer.Deserialize(sr);
                }
            }
        }

        private string GetPdfLableUrl(string token, string trackNumber, string host)
        {
            string requestXml = $@"<labelRequest>
                                    <printConfig>
                                        <labelFormat>pdf</labelFormat>
                                        <labelType>3</labelType>
                                        <labelSize>label_80x90</labelSize>
                                    </printConfig>
                                    <trackingNumbers>
                                    <trackingNumber>{trackNumber}</trackingNumber>
                                    </trackingNumbers>
                                   </labelRequest>";

            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest(Method.POST);
            request.AddParameter("request", requestXml);
            request.AddParameter("token", token);
            IRestResponse response = client.Execute(request);
            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception($"请求面单发生网络错误，{response.Content}");
            }

            var result = XmlDeserialize<_4PxResponse>(response.Content, Encoding.Default);
            if (!result.Success)
            {
                throw new Exception($"获取面单地址时发生错误：{result.ErrorMsg}");
            }

            string url = result.Datas.Data.FirstOrDefault();
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new Exception($"调用查询面单地址的接口成功，但是得到面单地址为空");
            }

            return url;
        }

        [Serializable]
        [XmlRoot("response")]
        public class _4PxResponse
        {
            [XmlElement("success")]
            public bool Success { get; set; }
            [XmlElement("datas")]
            public _4PxDatas Datas { get; set; }
            [XmlElement("errorCode")]
            public string ErrorCode { get; set; }
            [XmlElement("errorMsg")]
            public string ErrorMsg { get; set; }
        }
        [Serializable]
        public class _4PxDatas
        {
            [XmlElement("data")]
            public string[] Data { get; set; }
        }
        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            bool isSuccess = false;
            IRestResponse restResponse = null;
            int nums = 1;
            string errorMessage = "";
            do
            {
                var restClient = new RestClient(result.DownloadUrl);
                restResponse = await restClient.ExecuteAsync(new RestRequest());
                if (restResponse.StatusCode != System.Net.HttpStatusCode.OK || restResponse.RawBytes.Length < 2000)
                {
                    errorMessage = "数据已提交至4Px--->error:{0};contnet:{1}".Formater(restResponse.ErrorMessage, restResponse.Content);
                }
                else
                {
                    isSuccess = true;
                }
                nums++;
            } while (!isSuccess && nums < 3);
            if (!isSuccess)
            {
                throw new Exception(errorMessage);
            }
            return restResponse.RawBytes;
        }
    }
}
