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;

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

        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 Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            string method = "createOrder";
            var request = CreacteRequcet(order, goods, channel);
            try
            {
                var response = send<orderRequest, orderResponse>(channel, method, request);
                return Task.FromResult(new UploadResult
                {
                    TrackingNumber = response.shipId,
                    IsSuccess = true,
                    LazyDownloadLabel = false
                });
            }
            catch(Exception ex)
            {
                if (ex.Message == "重复下单")
                {
                    string queryOrderMethod = "queryOrder";
                    var getOrderResponse = send<dynamic, orderResponse>(channel, queryOrderMethod, new { orderId = request.orderId});
                    return Task.FromResult(new UploadResult
                    {
                        TrackingNumber = getOrderResponse.shipId,
                        IsSuccess = true,
                        LazyDownloadLabel = false
                    });
                }
                else
                    throw ex;
            }
            
        }

        private orderRequest CreacteRequcet(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            string orderId = order.SystemNo;
            
            orderRequest orderRequest = new orderRequest
            {
                senderAddress = channel.SenderStreet,
                senderArea = channel.SenderCity,
                senderCity = channel.SenderCity,
                senderCountry = channel.SenderCountryCode,
                senderCompany = channel.SenderCompany,
                senderEmail = channel.SenderEmail,
                senderName = channel.SenderName,
                senderProvince = channel.SenderState,
                senderTel = channel.SenderPhone,
                senderZipCode = channel.SenderZipCode,
                currency = goods.First().DeclareCurrency,
                receiveCity = order.ReceiverCity,
                receiveCompany = String.IsNullOrEmpty(order.ReceiverCompany) ? order.ReceiverName : order.ReceiverCompany,
                receiveCountry = order.ReceiverCountryCode,
                receiveZipCode = order.ReceiverZipCode,
                dutyType = "DDP",
                orderId = orderId,
                parcelQty = 1,
                parcelWeight = (order.CustomerWeight / 1000.0).ToString("0.00"),
                receiveAddress = order.ReceiverStreet,
                receiveArea = order.Area,
                receiveEmail = order.ReceiverEmail,
                receiveName = order.ReceiverName,
                receiveProvince = order.ReceiverState,
                receiveTel = order.ReceiverPhone,
                remark = "xyy",
            };
            orderRequest.items = goods.Select(x => new ItemsItem
            {
                currency = x.DeclareCurrency,
                hsCode = x.HsCode,
                name = x.CnName,
                qty = x.Quantity.ToString(),
                weight = (x.Weight / 1000.0).ToString("0.00"),
                skuCode = x.GoodsNumber,
                englishName = x.EnName,
                brand = string.Empty,
                unitPrice = x.DeclareFee.ToString("0.00")
            }).ToList();
            return orderRequest;
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            string method = "queryLabel";
            var req = new
            {
                orderId = order.SystemNo,
                shipId = result.TrackingNumber
            };
            var response = send<dynamic, labelResponse>(channel, method, req);

            if (!string.IsNullOrEmpty(response.fileUrl))
            {
                var fileUrl = response.fileUrl;
                System.Net.WebClient client = new System.Net.WebClient();
                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        byte[] data = await client.DownloadDataTaskAsync(fileUrl);
                        int minLenght = 5 * 1024;
                        if (data.Length >= minLenght)
                            return data;
                        else
                            System.Threading.Thread.Sleep(3000);
                    }
                    catch (Exception ex)
                    {
                        //三秒重试
                        System.Threading.Thread.Sleep(3000);
                    }
                }
                throw new Exception(this.ServiceName + " 面单下载失败，面单内容过小");
            }
            else
            {
                throw new Exception(this.ServiceName + " 获取面单地址失败");
            }
        }

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

        private T2 send<T1, T2>(Logistics_Channel channel, string method, T1 data)
        {
            RestSharp.RestClient client = new RestSharp.RestClient(channel.ApiHost);
            RestSharp.RestRequest request = new RestSharp.RestRequest(RestSharp.Method.POST);
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
            string sign = XYY.Common.Standard.String.Encryption.Md532(json + channel.ApiSecret);
            var postData = new
            {
                account = channel.ApiKey,
                token = channel.ApiSecret,
                method = method,
                productType = channel.ServiceChannelCode,
                sign = sign,
                jsonData = json
            };
            request.AddJsonBody(postData);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                baseResponse<T2> result = Newtonsoft.Json.JsonConvert.DeserializeObject<baseResponse<T2>>(response.Content);
                if (result.code == 0)
                    return result.data;
                else 
                    throw new Exception(result.message);
            }
            else
            {
                throw new Exception(this.ServiceName + "-API Error:" + response.ErrorMessage ?? response.Content);
            }
        }

        private class baseResponse<T>
        {
            public int code { get; set; }
            public string message { get; set; }

            public T data { get; set; }
        }
    }
}
