using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Tls;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using XYY.Common.Standard;
using XYY.Core.Standard;
using XYY.Core.Standard.ExtendMethods;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Service.Standard.ChannelApi.ChinaPost;
using XYY.Service.Standard.ChannelApi.PostNL.Model;

namespace XYY.Service.Standard.ChannelApi.PSE
{
    public class Api : IBaseApi
    {
        //private readonly int ChannelId = 18;


        public string ServiceName => "PaiSongYi";

        public async Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {
            List<BagDeclareErrosResult> resultList = new List<BagDeclareErrosResult>();
            var list = new List<BoxDetailItem>(bagDeclareRequest.BatchDeclare.SelectMany(x => x.Value));
            var g = list.GroupBy(x => new { x.LadingBillNumber, x.Port });
            foreach (var item in g)
            {
                try
                {
                    //请求数据处理
                    ManifestRequestBody body = new ManifestRequestBody();
                    body.batchNo = item.Key.LadingBillNumber;
                    body.forecastTime = DateTime.Now.ToString_yyyyMMdd();
                    body.warehouse = item.Key.Port;
                    body.orderList = new List<OrderListItem>();
                    foreach (var detailItem in item)
                    {
                        OrderListItem order = new OrderListItem()
                        {
                            boxNo = detailItem.BoxNumber,
                            trackNumber = detailItem.TrackingNumber,
                            weight = detailItem.OPWeight / 1000.0d,
                        };
                        body.orderList.Add(order);
                    }
                    await submitData(body, bagDeclareRequest.Channel);
                }
                catch (Exception ex)
                {
                    resultList.Add(new BagDeclareErrosResult() { LadingBillNumber = item.Key.LadingBillNumber, ErrorMessage = ex.Message });
                }
            }
            return resultList;
        }

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

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

        private int CreateWareHouseId(string receiverZipcode)
        {
            var portCode = PBPortData.USPort.GetPBPort(receiverZipcode);
            if (portCode == "LAX")
                return 1;
            else if (portCode == "ONT")
                return 2;
            else if (portCode == "EWR")
                return 3;
            else if (portCode == "ORD")
                return 4;
            else throw new Exception("不是识别邮编对应分区");
        }

        private RestRequest CreateRequest(Logistics_Channel channel, long timeStamp)
        {
            string customerCode = channel.ApiKey;

            string appKey = channel.ApiSecret;
            RestRequest request = new RestRequest();
            string sign = CreateSign(customerCode, appKey, timeStamp);
            request.AddHeader("timeStamp", timeStamp.ToString());
            request.AddHeader("sign", sign);
            request.AddHeader("customerCode", customerCode);
            request.Method = Method.POST;
            return request;
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            List<string> systemNos = new List<string>()
            {
                "XYYEX0028362153YQ",
                "XYYEX0028391833YQ",
                "XYYEX0028365938YQ",
                "XYYEX0028421507YQ",
                "XYYEX0028336961YQ",
                "XYYEX0028411479YQ",
                "XYYEX0028316417YQ",
                "XYYEX0028423565YQ",
                "XYYEX0028411675YQ",
                "XYYEX0028306780YQ",
                "XYYEX0028269157YQ",
                "XYYEX0028334621YQ",
                "XYYEX0028321190YQ",
                "XYYEX0028450740YQ",
                "XYYEX0028264454YQ",
                "XYYEX0028422364YQ",
                "XYYEX0028400421YQ",
                "XYYEX0028306296YQ",
                "XYYEX0028315662YQ",
                "XYYEX0028347167YQ",
                "XYYEX0028378399YQ",
                "XYYEX0028418968YQ",
                "XYYEX0028435314YQ",
                "XYYEX0028430863YQ"
            };




            string customerCode = channel.ApiKey;
            long timeStamp = GetTimeStamp();

            RestClient restClient = new RestSharp.RestClient(channel.ApiHost);
            RestRequest request = CreateRequest(channel, timeStamp);

            request.Resource = "/admin/Api/OpenV1/AddOrder";

            var param = CreateCreateOrderParam(order, goods, channel, customerCode);
            if (systemNos.Contains(param.csRefNo))
            {
                param.csRefNo += "CP2";
            }
            request.AddJsonBody(param);

            var response = await restClient.ExecuteAsync<CreateOrderResult>(request);
            if (response.IsSuccessful)
            {
                var result = response.Data;
                if (result == null)
                {
                    string msg = "下单API返回响应无效";
                    return new UploadResult { Error = msg };
                }
                if (!result.Success)
                {
                    string msg = $"下单API返回错误:{result.Message}";
                    return new UploadResult { Error = msg };
                }
                else
                {
                    string port = null;
                    if (order.ChannelId == 280)
                    {
                        if (!string.IsNullOrEmpty(order.ReceiverZipCode))
                        {
                            string YYZList = "A/B/C/E/G/H/J/K/L/M/N/P";
                            string YVRList = "R/S/T/V/X/Y";
                            string zipStart = order.ReceiverZipCode.Substring(0, 1);
                            if (YYZList.Contains(zipStart, StringComparison.InvariantCultureIgnoreCase))
                            {
                                port = "YYZ";
                            }
                            else if (YVRList.Contains(zipStart, StringComparison.InvariantCultureIgnoreCase))
                            {
                                port = "YVR";
                            }
                        }
                    }

                    return new UploadResult
                    {
                        IsSuccess = true,
                        ServiceOrderNumber = result.OrderNo,
                        TrackingNumber = result.TrackingNo,
                        destinationCode = port
                    };
                }
            }
            else
            {
                return new UploadResult { Error = "API下单失败:" + response.Content ?? response.ErrorMessage };
            }
        }

        private CreateOrderParam CreateCreateOrderParam(Order_Order order, List<Order_OrderGoods> orderGoods, Logistics_Channel channel, string customerCode)
        {
            var totalWeight = order.OPWeight == 0 ? order.CustomerWeight : order.OPWeight;

            string senderAddress = $"{channel.SenderStreet},{channel.SenderCity},{channel.SenderZipCode},{channel.SenderState}";
            string senderName = channel.SenderName;
            if (order.CustomerId == 876)
            {
                senderName = "RETURN DEPARTMENT";
                senderAddress = "42261 Zevo Dr Temecula CA 92590";
            }
            var addressArr = XYY.Core.Standard.ExtendMethods.StringExtendMethods.ToArray(order.ReceiverStreet, 270);

            List<OrderDetailsItem> orderDetails = new List<OrderDetailsItem>();
            orderGoods.ForEach(g =>
            {

                OrderDetailsItem item = new OrderDetailsItem
                {
                    cnName = g.CnName,
                    enName = g.EnName,
                    hsCode = g.HsCode,
                    quantity = g.Quantity,
                    singlePrice = g.DeclareFee,
                    singleWeight = g.Weight / 1000m
                };
                orderDetails.Add(item);

            });

            if (channel.ServiceChannelCode == "26")
            {
                orderDetails.ForEach(i => i.hsCode = null);
            }

            string poZipCode = string.Empty;
            if (channel.ServiceChannelCode.Contains("34"))
            {
                //渠道34
                if (order.Height == 0)
                    order.Height = 1m;
                if (order.Width == 0)
                    order.Width = 1m;
                if (order.Length == 0)
                    order.Length = 1m;
                poZipCode = channel.ServiceChannelCode.Split(";")[1];
                channel.ServiceChannelCode = channel.ServiceChannelCode.Split(';')[0];
            }

            List<OrderBagsItem> orderBags = new List<OrderBagsItem> { };

            OrderBagsItem bagsItem = new OrderBagsItem
            {
                bagsHeight = order.Height,
                bagsLength = order.Length,
                bagsWeight = totalWeight / 1000m,
                bagsWidth = order.Width
            };
            orderBags.Add(bagsItem);

            OrderExtJson extJson = new OrderExtJson
            {
                recipientDocumentNumber = "CPF"
            };

            string extJsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(extJson);


            int wareHouseId = 0;
            if (channel.Id == 224)
            {
                wareHouseId = CreateWareHouseId(order.ReceiverZipCode);
            }


            int serviceChannelId = 0;
            bool serviceChannelIdOk = int.TryParse(channel.ServiceChannelCode, out serviceChannelId);
            if (!serviceChannelIdOk || serviceChannelId <= 0)
            {
                throw new Exception("服务渠道设置无效");
            }

            string referenceNo = order.SystemNo;
            //高欧君加拿大面单需要显示客单号
            if (channel.Id == 280 && order.CustomerId == 353)
            {
                referenceNo = order.CustomerOrderNo;
            }

            if (order.CustomerId == 676)
            {
                referenceNo = order.CustomerOrderNo;
            }

            CreateOrderParam param = new CreateOrderParam
            {
                channelID = serviceChannelId,
                customerCode = customerCode,
                csRefNo = referenceNo,
                warehouseID = wareHouseId,
                totalWeight = totalWeight / 1000m,
                senderName = senderName,
                sendAddress = senderAddress,
                recipientName = order.ReceiverName,
                recipientCountry = order.ReceiverCountryCode,
                recipientAddress1 = addressArr[0],
                recipientAddress2 = addressArr.Length > 1 ? addressArr[1] : null,
                recipientState = order.ReceiverState,
                recipientCity = order.ReceiverCity,
                recipientZipCode = order.ReceiverZipCode,
                orderDetails = orderDetails,
                orderBags = orderBags,
                orderExtJson = extJsonStr,
                recipientContact = order.ReceiverPhone
            };



            if (param.channelID == 34)
            {
                param.orderExtJson = "{\"poZipCode\":\"" + poZipCode + "\"}";
                param.sender = senderName;
                if (order.CustomerId != 876)
                {
                    param.sendPhone = channel.SenderPhone;
                    param.sendState = channel.SenderState;
                    param.sendCity = channel.SenderCity;
                    param.sendCountry = channel.SenderCountryCode;
                    param.sendZipCode = channel.SenderZipCode;
                    param.sendAddress = channel.SenderStreet;

                }
                else
                {
                    param.sendPhone = "0000000000";
                    param.sendState = "CA";
                    param.sendCity = "Temecula";
                    param.sendCountry = "US";
                    param.sendZipCode = "92590";
                    param.sendAddress = "42261 Zevo Dr";

                }
            }
            return param;
        }

        private string CreateSign(string customerCode, string appKey, long timeStamp)
        {
            string raw = $"{customerCode}{appKey}{timeStamp}";
            string sign = MD5Util.Get(raw);
            return sign;
        }

        private long GetTimeStamp()
        {
            long timeStamp = DateTime.Now.Ticks / 1000;
            return timeStamp;
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            //重试两次 

            long timeStamp = GetTimeStamp();

            RestClient restClient = new RestSharp.RestClient(channel.ApiHost);
            RestRequest request = CreateRequest(channel, timeStamp);
            request.Resource = "/admin/Api/OpenV1/GetLabel";
            GetLabelParam param = new GetLabelParam
            {
                orderNo = result.TrackingNumber,
                orderNoType = 3
            };
            request.AddJsonBody(param);
            int getQty = 1;
        srtGetLabel:
            var response = await restClient.ExecuteAsync<GetLabelResult>(request);

            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                GetLabelResult labelResult = response.Data;
                if (labelResult == null)
                {
                    string msg = "获取面单API返回响应无效";
                    throw new Exception(msg);
                }
                if (labelResult.Success)
                {
                    if (labelResult.Labels?.Any() != true)
                    {
                        if (getQty < 3)
                        {
                            getQty++;
                            System.Threading.Thread.Sleep(2000);
                            goto srtGetLabel;
                        }
                        else
                        {
                            throw new Exception("获取面单API返回标签数据为空");
                        }

                    }
                    var label = labelResult.Labels.First();
                    if (string.IsNullOrWhiteSpace(label.LabelBase64))
                    {
                        if (getQty < 3)
                        {
                            getQty++;
                            System.Threading.Thread.Sleep(2000);
                            goto srtGetLabel;
                        }
                        else
                        {
                            throw new Exception("获取面单API返回标签数据为空");
                        }
                    }

                    try
                    {
                        var bytes = Convert.FromBase64String(label.LabelBase64);
                        return bytes;
                    }
                    catch (Exception ex)
                    {
                        throw new Exception($"解析标签数据失败:{ex.Message}");

                    }

                }
                else
                {
                    throw new Exception($"面单下载失败:{labelResult.Message}");
                }
            }
            else
            {
                throw new Exception("面单下载失败 " + response.ErrorMessage ?? response.Content);
            }
        }

        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            long timeStamp = GetTimeStamp();
            RestClient restClient = new RestSharp.RestClient(logistics_ChannelCancel.ApiHost);
            RestRequest request = CreateRequest(new Logistics_Channel
            {

                ApiSecret = logistics_ChannelCancel.ApiSecret,
                ApiKey = logistics_ChannelCancel.ApiKey
            }, timeStamp);
            request.Resource = "/admin/Api/OpenV1/voidOrder";
            var param = new
            {
                orderNoType = 3,
                orderNo = logistics_ChannelCancel.TrackingNumber
            };

            request.AddJsonBody(param);
            var response = restClient.Post<GetLabelResult>(request);
            if (!response.IsSuccessful)
            {
                throw new Exception(response.ErrorMessage);
            }
        }
        private async Task submitData(ManifestRequestBody body, Logistics_Channel channel)
        {
            //处理api请求
            long timeStamp = GetTimeStamp();
            string json = JsonConvert.SerializeObject(body);
            RestClient client = new RestClient(channel.ApiHost);
            RestRequest request = CreateRequest(channel, timeStamp);
            request.Resource = "/admin/api/channel/aci/createManifest";
            request.AddParameter("application/json", json, ParameterType.RequestBody);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JsonConvert.DeserializeObject<ManifestRequestResponse>(response.Content);
                if (result.code != 0)
                {
                    throw new Exception($"派送翼预报失败:{result.msg}");
                }
            }
            else
            {
                throw new Exception($"派送翼预报失败，错误状态码:{response.StatusCode},{response.Content}");
            }
        }
    }
}
