using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Hosting;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using XYY.Core.Standard.ExtendMethods;
using XYY.Core.Standard.PDF;
using XYY.Data.Standard.Order;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.AddressHelper;
using XYY.Service.Standard.ChannelApi.Base;

namespace XYY.Service.Standard.ChannelApi.Itdida
{
    public class ItdidaApi : IBaseApi
    {
        public string ServiceName => "Itdida";

        const string tokenCacheKey = "$ItdidaTokenCache$";
        private static readonly object syncRoot = new object();
        //private static TokenObject tokenObj = null;

        private IOrderRepository _orderRepository { get; set; }
        private readonly IDistributedCache _cache;

        public ItdidaApi(IOrderRepository orderRepository, IDistributedCache cache)
        {
            _orderRepository = orderRepository;
            _cache = cache;
        }


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

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

        public 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)
        {
            if (channel.Id == 330)
            {
                if (order.ReceiverCity.Contains("'"))
                {
                    order.ReceiverCity = order.ReceiverCity.Replace("'", "");
                }
            }
            if (order.ReceiverCountryCode == "US")
            {
                int[] fedexChannelIds = new int[] { 359, 360, 361, 362, 439, 440, 441, 442 };
                bool checkRemote = !fedexChannelIds.Contains(channel.Id);
                new USAddressCheck().CheckUSOrder(order, checkRemote);
            }
            if (goods.Sum(x => x.DeclareFee * x.Quantity) > 400)
            {
                decimal sumDeclareFee = goods.Sum(x => x.DeclareFee * x.Quantity);
                goods.ForEach(x =>
                {
                    x.DeclareFee = (decimal)(Math.Ceiling(x.DeclareFee * x.Quantity / sumDeclareFee * 400 / x.Quantity * 100) / 100);
                });
            }
            string host = channel.ApiHost;
            var shippmentInfo = CreateShipmentInfo(channel, order, goods);
            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/itdida-api/yundans");
            request.Method = Method.POST;

            var body = new List<ShipmentInfo> { shippmentInfo };
            request.AddJsonBody(body);
            string dbody = Newtonsoft.Json.JsonConvert.SerializeObject(body);

            string token = GetToken(channel);

            request.AddHeader("Authorization", token);




            var response = await client.ExecuteAsync(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var content = response.Content;
                if (string.IsNullOrWhiteSpace(content))
                {
                    throw new Exception("下单api返回内容为空");
                }

                CreateShippmentResult data = null;
                try
                {
                    data = Newtonsoft.Json.JsonConvert.DeserializeObject<CreateShippmentResult>(content);
                }
                catch (Exception ex)
                {
                    throw new Exception($"解析下单响应时出错:{ex.Message},内容:{content}", ex);
                }
                if (data.success == true)
                {
                    if (data.data?.Any() == true)
                    {
                        var shippmentResultItem = data.data[0];

                        bool alreadyCreateOrder = CheckRepeatCreateOrder(shippmentResultItem.message);
                        if (shippmentResultItem.code != 200 || (shippmentResultItem.message != "成功" && !alreadyCreateOrder))
                        {
                            if (shippmentResultItem.message.Equals("该客户没有获取转单的权限") || shippmentResultItem.message.Equals("Label权限不足"))
                            {
                                return new UploadResult
                                {
                                    IsSuccess = true,
                                    ServiceOrderNumber = shippmentResultItem.xiTongDanHao,
                                    TrackingNumber = shippmentResultItem.xiTongDanHao
                                };
                            }
                            string msg = $"下单API返回错误:{shippmentResultItem.message}";
                            if (msg.Contains("根据排货规则未找到适用的成本价"))
                            {
                                msg += "(可能由于地址错误)";
                            }
                            throw new Exception(msg);
                        }
                        else
                        {
                            string trackingNumber = shippmentResultItem.zhuanDanHao;
                            string label = String.IsNullOrEmpty(shippmentResultItem.label) ? shippmentResultItem.labelUrl : shippmentResultItem.label;
                            string serviceOrderId = shippmentResultItem.xiTongDanHao;
                            if (string.IsNullOrWhiteSpace(trackingNumber))
                            {
                                string msg = $"下单API返回错误:获取的跟踪号为空";
                            }
                            if (string.IsNullOrWhiteSpace(label))
                            {
                                string msg = $"下单API返回错误:获取的面单数据为空";
                            }

                            if (!alreadyCreateOrder)
                            {
                                await _orderRepository.AddChannelOrderInfoRecord(channel.Id, serviceOrderId, order.SystemNo);
                            }


                            var result = new UploadResult
                            {
                                IsSuccess = true,
                                ServiceOrderNumber = serviceOrderId,
                                TrackingNumber = trackingNumber,
                                DownloadUrl = label
                            };
                            return result;
                        }
                    }
                    else
                    {
                        throw new Exception("下单api返回订单数据为空");
                    }

                }
                else
                {
                    string msg = content;
                    throw new Exception($"下单出错 {msg}");
                }
            }
            else
            {
                string msg = string.IsNullOrWhiteSpace(response.ErrorMessage) ? response.Content : response.ErrorMessage;
                throw new Exception(msg);
            }
        }

        private bool CheckRepeatCreateOrder(string message)
        {
            return !string.IsNullOrWhiteSpace(message) && message.Contains("客户单号重复,已返回原数据");
        }

        private List<ShenBaoXinXiListItem> CreateDeclareItems(List<Order_OrderGoods> goodsList)
        {
            List<ShenBaoXinXiListItem> items = new List<ShenBaoXinXiListItem>();
            var goodsGroup = goodsList.GroupBy(x => new { x.DeclareFee, x.HsCode, x.CnName, x.EnName, x.Quantity, x.Material, x.Remark });
            foreach (var g in goodsGroup)
            {
                string rmk = g.Key.Remark == null ? string.Empty : Regex.Replace(g.Key.Remark, "[\u4e00-\u9fa5]{1,}", string.Empty);
                ShenBaoXinXiListItem item = new ShenBaoXinXiListItem
                {
                    shenBaoDanJia = g.Key.DeclareFee,
                    shenBaoHaiGuanBianMa = g.Key.HsCode,
                    shenBaoJinE = g.Sum(x => x.DeclareFee * x.Quantity),
                    shenBaoPinMing = g.Key.EnName + rmk,
                    shenBaoShuLiang = g.Sum(x => x.Quantity),
                    zhongWenPinMing = g.Key.CnName,
                    caiZhiCn = g.Key.Material,
                    caiZhiEn = rmk,
                    tradeMark = "",
                    yongTuCn = "家居用品",
                    yongTuEn = "Housewear"
                };
                items.Add(item);
            }
            return items;
        }

        private ShipmentInfo CreateShipmentInfo(Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> goodsList)
        {
            string orderNumber = order.SystemNo;
            if (order.IsOnline && channel.Id == 330)
            {
                orderNumber = order.SystemNo + "OL";
                if (order.CustomerWeight > 5000)
                    order.CustomerWeight = 4000;
            }
            else if (channel.Id == 509)
            {
                orderNumber = order.SystemNo.Replace("XYYEX", "A");
            }
            else
            {
                orderNumber = order.SystemNo;
            }

            string clientCode = channel.ApiKey;
            string serviceChannelCode = channel.ServiceChannelCode.Split(';')[0];
            int channeType = int.Parse(channel.ServiceChannelCode.Split(';')[1]);
            double opWeightKg = (order.OPWeight <= 0 ? order.CustomerWeight : order.OPWeight) / 1000d;

            //if (order.ChannelId == 370)
            //{
            //    order.ReceiverName = "SINO-US INTERNATIONAL ATTN. LOUIS LIN";
            //    order.ReceiverPhone = "6263403789";
            //    order.ReceiverCountryCode = "US";
            //    order.ReceiverState = "CA";
            //    order.ReceiverCity = "Hawthorne";
            //    order.ReceiverStreet = "12911 Simms Ave.";
            //    order.ReceiverZipCode = "90250";
            //}

            var items = CreateDeclareItems(goodsList);

            ShipmentInfo shipmentInfo = new ShipmentInfo
            {
                baoGuanFangShi = 0,
                baoGuoLeiXing = 1,
                clientCode = clientCode,// "W00115",
                fuShuiJin = 0,
                guoJia = order.ReceiverCountryCode,
                jianShu = 1,
                jiJianGongSiMingCheng = channel.SenderCompany,
                jiJianRenDianHua = channel.SenderPhone,
                jiJianRenDiZhi1 = channel.SenderStreet,
                jiJianRenDiZhi2 = null,
                jiJianRenDiZhi3 = null,
                jiJianRenMingCheng = channel.SenderName,
                keHuDanHao = orderNumber,
                recipientEmail = null,
                requiredTrackNo = true,
                requiredZhuanDanFaPiao = false,
                shenBaoXinXiList = items,
                shouHuoQuDao = serviceChannelCode,// "USSPDL-PHCX",
                shouHuoShiZhong = opWeightKg,
                shouJianRenChengShi = order.ReceiverCity,
                shouJianRenDianHua = order.ReceiverPhone,
                shouJianRenDiZhi1 = order.ReceiverStreet,
                shouJianRenDiZhi2 = null,
                shouJianRenDiZhi3 = null,
                shouJianRenGongSi = null,
                shouJianRenShouJi = null,
                shouJianRenXingMing = order.ReceiverName,
                shouJianRenYouBian = order.ReceiverZipCode,
                wuLiuFangShi = channeType,
                zhouMing = order.ReceiverState
            };



            //Fedex 自主包装传入 尺寸
            //SGH-Fedex-C-W SGH-Fedex-D-W
            if (channel.PublicName == "SGH-Fedex-C-W" ||
                channel.PublicName == "SGH-Fedex-D-W" ||
                channel.PublicName == "SHG-FEDEX-TJ-W" ||
                channel.PublicName == "SHG-DGFEDEX-A-W")
            {
                shipmentInfo.baoGuoLeiXing = 1;
                shipmentInfo.danJianList = new List<DanJianListItem>();
                shipmentInfo.danJianList.Add(new DanJianListItem
                {
                    chang = order.Length,
                    kuan = order.Width,
                    gao = order.Height,
                    shiZhong = opWeightKg
                });

            }
            else if (channel.PublicName == "SGH-DHL-C")
            {
                shipmentInfo.baoGuoLeiXing = 1;
                shipmentInfo.danJianList = new List<DanJianListItem>();
                shipmentInfo.danJianList.Add(new DanJianListItem
                {
                    chang = order.Length,
                    kuan = order.Width,
                    gao = order.Height,
                    shiZhong = opWeightKg,
                });
            }
            else if (channel.PublicName == "YH-US-MG" || channel.PublicName == "YH-US-TH" || channel.PublicName == "YH-US-DD" || channel.PublicName == "WG-US-MP")
            {
                shipmentInfo.baoGuoLeiXing = 1;
            }

            else
            {
                //2022-06-08万国优联建议包裹类型设定为1
                if (channel.Id == 251 || channel.Id == 323 || channel.Id == 330 || channel.Id == 334 || channel.Id == 342)
                {
                    shipmentInfo.baoGuoLeiXing = 1;
                }
                else
                    shipmentInfo.baoGuoLeiXing = 2;//原本是2
            }

            if (shipmentInfo.shouJianRenDiZhi1.Length > 30)
            {
                var list = shipmentInfo.shouJianRenDiZhi1.ToArray(30);
                if (list.Length > 3)
                    throw new Exception("地址超长");
                else
                {
                    if (list.Length == 3)
                    {
                        shipmentInfo.shouJianRenDiZhi1 = list[0];
                        shipmentInfo.shouJianRenDiZhi2 = list[1];
                        shipmentInfo.shouJianRenDiZhi3 = list[2];
                    }
                    else if (list.Length == 2)
                    {
                        shipmentInfo.shouJianRenDiZhi1 = list[0];
                        shipmentInfo.shouJianRenDiZhi2 = list[1];
                    }
                    else
                    {
                        shipmentInfo.shouJianRenDiZhi1 = list[0];
                    }
                }
            }
            return shipmentInfo;
        }

        //public string[] ToArray(string str, int maxLength)
        //{
        //    string[] arr = str.Split(' ', '.');
        //    int page = ((str.Length + maxLength) - 1) / maxLength;
        //    string[] addressArr = new string[page];

        //    int flag = 0;
        //    int t = arr.Count();
        //    for (int i = 0; i < page; i++)
        //    {
        //        string temp = "";
        //        for (int j = 0; j < t; j++)
        //        {
        //            if ((temp += arr[flag] + " ").Length <= maxLength)
        //            {
        //                addressArr[i] += arr[flag] + " ";
        //                flag++;
        //            }
        //        }
        //        t = arr.Count() - flag;
        //    }
        //    return addressArr;
        //}



        private string RequestToken(Logistics_Channel channel)
        {
            string host = channel.ApiHost;
            string userName = channel.ApiKey;//"W00115"
            string password = channel.ApiSecret;//"XYY123456"

            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/itdida-api/login");
            request.AddParameter("username", userName);
            request.AddParameter("password", password);
            request.Method = Method.POST;
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {

                var content = response.Content;
                if (string.IsNullOrWhiteSpace(content))
                {
                    throw new Exception("api返回内容为空");
                }

                LoginResult data = null;
                try
                {
                    data = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginResult>(content);
                }
                catch (Exception ex)
                {
                    throw new Exception($"解析登录响应时出错:{ex.Message},内容:{content}", ex);
                }

                if (data.success == true)
                {
                    if (!string.IsNullOrWhiteSpace(data.data))
                    {
                        return data.data;
                    }
                    else
                    {
                        throw new Exception("api返回token为空");
                    }

                }
                else
                {
                    string msg = data.data;
                    throw new Exception($"API授权出错 {msg}");
                }
            }
            else
            {
                string msg = string.IsNullOrWhiteSpace(response.ErrorMessage) ? response.Content : response.ErrorMessage;
                throw new Exception(msg);
            }
        }

        /// <summary>
        /// 获取token。渠道要求token48小时过期。先从静态变量中获取，如果不存在或已过期则从api中获取
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        public string GetToken(Logistics_Channel channel)
        {
            string channelTokenCacheKey = tokenCacheKey + channel.Id;
            int expiredHours = 1;

            string token = _cache.GetString(channelTokenCacheKey);

            if (!string.IsNullOrWhiteSpace(token))
            {
                return token;
            }
            else
            {
                lock (syncRoot)
                {
                    token = _cache.GetString(channelTokenCacheKey);
                    if (!string.IsNullOrWhiteSpace(token))
                    {
                        return token;
                    }
                    else
                    {
                        token = RequestToken(channel);
                        var cacheOpt = new DistributedCacheEntryOptions
                        {
                            AbsoluteExpirationRelativeToNow = new TimeSpan(expiredHours, 0, 0)
                        };
                        _cache.SetStringAsync(channelTokenCacheKey, token, cacheOpt);
                        return token;
                    }
                }
            }


        }

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

            var bytes = await Task.Run(() =>
            {
                try
                {
                    string base64 = result.DownloadUrl;
                    byte[] data = null;
                    if (channel.Id == 370)
                    {
                        return null;
                    }
                    else
                    {

                        if (result.DownloadUrl.StartsWith("http"))
                        {
                            data = new System.Net.WebClient().DownloadData(result.DownloadUrl);
                            if (data.Length < 1000)
                                throw new Exception("面单获取失败");
                        }
                        else
                        {

                            data = Convert.FromBase64String(base64);
                        }
                        if (channel.Id == 334 && order.CustomerId == 454)
                        {
                            string goodsCount = orderGoods.Sum(g => g.Quantity).ToString();
                            data = PDFHelper.Watermark(data, goodsCount, 1, 255, 65, 10, iTextSharp.text.BaseColor.BLACK);
                        }
                    }
                    return data;
                }
                catch (Exception ex)
                {
                    throw new Exception("解析面单base64数据失败", ex);
                }
            });
            return bytes;
        }

        public async Task<byte[]> GetFP(Logistics_Channel channel, string trackingNumber)
        {
            string token = GetToken(channel);
            string host = channel.ApiHost;

            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest($"/itdida-api/files?keHuDanHaoList={trackingNumber}&wenJianLeiXingList=4", Method.POST);
            request.AddHeader("Authorization", token);
            var response = client.Execute(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = Newtonsoft.Json.JsonConvert.DeserializeObject<FPResult>(response.Content);
                if (result.success == "true")
                {
                    if (!string.IsNullOrEmpty(result.data[0].fileList[0].data)) { return Convert.FromBase64String(result.data[0].fileList[0].data); }
                    else
                    {
                        WebClient webClient = new WebClient();
                        return webClient.DownloadData(result.data[0].fileList[0].url);
                    }

                }
                else
                {
                    throw new Exception(result.data[0].message);
                }
            }
            else
            {
                throw new Exception(response.ErrorMessage);
            }


        }
        //如果好用，请收藏地址，帮忙分享。
        public class FPFileListItem
        {
            /// <summary>
            /// 
            /// </summary>
            public int code { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string data { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string format { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string message { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public int type { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string url { get; set; }
        }

        public class FPDataItem
        {
            /// <summary>
            /// 
            /// </summary>
            public int code { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public List<FPFileListItem> fileList { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string keHuDanHao { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string message { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string zhuanDanHao { get; set; }
        }

        public class FPResult
        {
            /// <summary>
            /// 
            /// </summary>
            public List<FPDataItem> data { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public int statusCode { get; set; }
            /// <summary>
            /// 
            /// </summary>
            public string success { get; set; }
        }

        public async Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            string token = GetToken(channel);
            RestClient client = new RestClient(channel.ApiHost);
            RestRequest request = new RestRequest("/itdida-api/queryYunDanDetail?danHaos=" + SystemNo);
            request.AddHeader("Authorization", token);
            var resultJson = client.Execute(request);
            if (resultJson.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception(resultJson.ErrorMessage ?? resultJson.Content);
            }
            var result = Newtonsoft.Json.JsonConvert.DeserializeObject<GetShippmentResult>(resultJson.Content);
            if (!result.success)
                throw new Exception(result.statusCode.ToString());
            return result.data[0].referenceNo;
        }
        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }
    }
}
