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 RestSharp;
using Microsoft.Extensions.Caching.Distributed;
using XYY.Common.Standard;
using XYY.Core.Standard.PDF;
using System.Text.RegularExpressions;

namespace XYY.Service.Standard.ChannelApi.HermesPUDO
{
    public class Api : IBaseApi
    {
        public Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 美元对欧元USD
        /// </summary>
        const decimal USDToEUR = 0.83m;
        const string tokenCacheKey = "@@HERMES_TOKEN_CACHE_KEY";
        public string ServiceName => "Hermes Border Guru-PUDO";

        //readonly string tokenUrl = "https://iris-preview.hermesborderguru.io/oauth/token";
        readonly string tokenUrl = "https://iris.hermesborderguru.io/oauth/token";

        IDistributedCache _distributedCache;
        public Api(IDistributedCache distributedCache)
        {
            _distributedCache = distributedCache;
        }

        private async Task<TokenInfo> GetTokenFromApi(Logistics_Channel channel)
        {
            string userName = channel.ApiKey;
            string userSecret = channel.ApiSecret;
            string auth = $"{userName}:{userSecret}";
            byte[] bytes = Encoding.UTF8.GetBytes(auth);
            string authBase64 = Convert.ToBase64String(bytes);
            string authHeader = $"Basic {authBase64}";
            RestRequest req = new RestRequest(Method.POST);

            req.AddHeader("Authorization", authHeader);
            req.AddHeader("content-type", "application/x-www-form-urlencoded");

            string formData = $"client_id={userName}&grant_type=client_credentials";
            req.AddParameter("application/x-www-form-urlencoded", formData, ParameterType.RequestBody);
            //req.AddParameter("client_id", userName, ParameterType.RequestBody);
            //req.AddParameter("grant_type", "client_credentials", ParameterType.RequestBody);

            RestClient restClient = new RestClient(tokenUrl);
            var resp = await restClient.ExecuteAsync<TokenInfo>(req);
            var token = resp.Data;
            return token;
        }

        private async Task<string> GetToken(Logistics_Channel channel)
        {
            var token = await _distributedCache.GetAsync(tokenCacheKey, async () =>
            {
                var result = await GetTokenFromApi(channel);
                return result?.access_token;
            });
            return token;
        }

        public string TrimEnd(string strSrc, string strTrim)
        {
            if (strTrim == " " || string.IsNullOrEmpty(strTrim))
            {
                return strSrc;
            }
            if (strSrc.EndsWith(strTrim))
            {
                string strDes = strSrc.Substring(0, strSrc.Length - strTrim.Length);
                return TrimEnd(strDes, strTrim);
            }
            return strSrc;
        }

        private PODRequest CreatePODRequest(Order_Order order, List<Order_OrderGoods> goods)
        {
            SourceAddress senderAddress = new SourceAddress
            {
                company = "Xingyunyi",
                lastName = null,
                street = null,//"Frankfurter Strasse 85",
                postcode = null,//"65479",
                city = null, //"Raunheim",
                country = "DE",
                addressAdditionalFields = null,// new List<string> { "c/o Souverign Courier" },
            };

            string street = order.ReceiverStreet, house = order.House;


            //if (string.IsNullOrWhiteSpace(order.House))
            //{

            //    Regex regex = new Regex(@"^.*?(?=\d)");
            //    var match = regex.Match(order.ReceiverStreet);
            //    if (!match.Success)
            //    {
            //        throw new Exception("德国专线地址内需要包含街道与数字门牌号");
            //    }
            //    else
            //    {
            //        house = regex.Replace(order.ReceiverStreet, "");
            //        street = match.Value.Replace(",", " ");
            //    }

            //    //string receiverStreet = order.ReceiverStreet.Trim();
            //    //string pattern = "^\\d+|\\d+$";
            //    //var regex = new Regex(pattern);
            //    //var match = regex.Match(receiverStreet);
            //    //if (match.Success)
            //    //{
            //    //    var val = match.Value;
            //    //    street = receiverStreet.Replace(val, string.Empty);
            //    //    house = val;
            //    //}
            //    //else
            //    //{
            //    //    throw new Exception("德国地址需要包含街道与门牌号");
            //    //}
            //}
            //else
            //{
            //    house = order.House;

            //    street = order.ReceiverStreet.Trim();
            //    //去掉门牌号重复的问题;
            //    street = TrimEnd(TrimEnd(street, house).Trim(), house);
            //}
            if (string.IsNullOrEmpty(order.ReceiverEmail))
                throw new Exception("请传入客户邮箱");

            Regex regex = new Regex(@"[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\.[a-zA-Z]+)+");
            if (!regex.IsMatch(order.ReceiverEmail))
                throw new Exception("邮箱格式错误，请检查邮箱地址");
            if (order.CustomerId != 7)
            {
                throw new Exception("仅指定客户可使用该渠道发货");
            }
            DestinationAddress destAddress = new DestinationAddress
            {
                firstName = string.Empty,
                lastName = order.ReceiverName,
                company = string.Empty,
                street = street,
                houseNo = string.Empty,// house,
                postcode = order.ReceiverZipCode,

                city = order.ReceiverCity,
                country = order.ReceiverCountryCode,
                phone = order.ReceiverPhone,
                mail = order.ReceiverEmail,

            };

            List<Item> items = new List<Item>();
            foreach (var g in goods)
            {
                Item item = new Item
                {
                    sku = string.IsNullOrEmpty(g.GoodsNumber) ? g.EnName : g.GoodsNumber,
                    category = "low",//"low", if value of Item is < 150,- Euro ,"high", if value of Item is > 150,-Euro
                    countryOfManufacture = "CN",
                    value = g.DeclareFee * USDToEUR,//USD 转 EUR
                    weight = g.Weight,
                    quantity = g.Quantity,
                    description = g.EnName,


                };
                items.Add(item);
            }

            ParcelData parcelData = new ParcelData
            {
                depth = order.Height,
                length = order.Length,
                width = order.Width,
                weight = order.OPWeight == 0 ? order.CustomerWeight : order.OPWeight,
                shipmentCost = null,
                packagingType = "PC",
                currency = "EUR",
                items = items,
            };

            var services = new Services
            {
                pudoDelivery = new PudoDelivery()
                {
                    autoSelect = string.IsNullOrEmpty(order.PudoId) || order.PudoId == "autoSelect" ? true : false,
                    pudoId = string.IsNullOrEmpty(order.PudoId) || order.PudoId == "autoSelect" ? null : order.PudoId
                }

            };

            var label = new Label
            {
                output = "PDF"
            };

            var customerReferences = new List<string> { order.TransferNumber };

            PODRequest request = new PODRequest
            {
                delivery = new RequestDelivery
                {
                    sourceAddress = senderAddress,
                    destinationAddress = destAddress,
                    parcelData = parcelData,
                    services = services,
                    label = label,
                    customerReferences = customerReferences,

                }
            };

            return request;
        }

        private async Task<UploadResult> CreateOrder(Logistics_Channel channel, PODRequest request, string token)
        {
            if (string.IsNullOrWhiteSpace(token) || token.Length < 8)//token.Length<8意思是避免出现一些"null"之类的值
            {
                var tokenInfo = await GetTokenFromApi(channel);
                token = tokenInfo?.access_token;
            }
            if (string.IsNullOrWhiteSpace(token))
            {
                throw new Exception($"token值:{token}无效");
            }

            RestRequest req = new RestRequest(Method.POST);
            req.AddJsonBody(request);
            req.AddHeader("Authorization", $"Bearer {token}");
            RestClient restClient = new RestClient(channel.ApiHost);
            var resp = await restClient.ExecuteAsync<CreatePodResponse>(req);

            if (!resp.IsSuccessful)
            {
                throw new Exception($"API返回失败:{resp.ErrorMessage} {resp.Content}");
            }
            string serviceOrderId = resp?.Data?.delivery?.orderId;
            if (string.IsNullOrEmpty(serviceOrderId))
                throw new Exception("下单失败，服务商返回订单ID为空");

            var barcodeInfos = resp.Data.delivery?.labelContent?.import?.barcodeObject;
            if (barcodeInfos?.Any() != true || barcodeInfos.Count == 0)
            {
                throw new Exception("下单失败，服务商返回订单数据缺失");
            }
            string trackingNum = resp.Data.delivery.labelContent.import.barcodeObject[0].barcode;
            if (string.IsNullOrEmpty(trackingNum))
                throw new Exception("下单失败，服务商返回运单号为空");


            string errorMsg = null;
            if (resp.StatusCode != System.Net.HttpStatusCode.OK)
            {
                errorMsg = resp.ErrorMessage;
            }
            else if (resp.ErrorException != null)
            {
                errorMsg = resp.ErrorException.Message;
            }


            var data = resp.Data;
            var labelBase64 = data?.delivery?.labelBase64;
            if (string.IsNullOrEmpty(labelBase64))
            {
                throw new Exception("面单内容为空");
            }



            //byte[] labelData = Convert.FromBase64String(labelBase64);
            UploadResult uploadResult = new UploadResult
            {
                ChannelId = channel.Id,
                DownloadUrl = data.delivery.labelBase64,
                Error = errorMsg,
                IsSuccess = errorMsg == null,
                IsTransfer = false,
                LabelData = null,
                LazyDownloadLabel = false,
                ResponseContent = resp.Content,
                ServiceOrderNumber = data.delivery.orderId,
                TrackingNumber = trackingNum,
            };
            return uploadResult;

        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            if (order.ReceiverCountryCode != "DE")
            {
                throw new Exception("该渠道仅对德国通邮");
            }
            //channel.ApiKey = "TESTD8MNHK";
            //channel.ApiSecret = "ytW8J424lQns6PGZ3phG";
            //channel.ApiHost = "https://iris-preview.hermesborderguru.io/request";
            var token = await GetToken(channel);
            var podRequest = CreatePODRequest(order, goods);
            var result = await CreateOrder(channel, podRequest, token);
            return result;
        }



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

            var base64Url = result.DownloadUrl;
            var data = Convert.FromBase64String(base64Url);
            if (channel.Id == 184)
            {
                data = PDFHelper.Watermark(data, "D", 1, 240, 100, 18, iTextSharp.text.BaseColor.BLACK);
            }
            if (data == null)
            {
                string base64 = result.DownloadUrl;
                var bytes = Convert.FromBase64String(base64);
                data = bytes;
            }
            return Task.Run(() => data);
        }

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

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

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