using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using XYY.Common.Standard;
using XYY.Core.Standard.FiddlerClient;
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.Base;
using XYY.Service.Standard.ChannelApi.GFSAPI.Model;

namespace XYY.Service.Standard.ChannelApi.GFSAPI
{
    public partial class Api : IBaseApi
    {
        #region 构造
        IOrder_OrderPrintQtyRepository _order_OrderPrintQtyRepository;
        IOrderApiDeclarationRepository _orderApiDeclarationRepository;
        public Api(IOrder_OrderPrintQtyRepository order_OrderPrintQtyRepository, IOrderApiDeclarationRepository orderApiDeclarationRepository)
        {
            this._order_OrderPrintQtyRepository = order_OrderPrintQtyRepository;
            this._orderApiDeclarationRepository = orderApiDeclarationRepository;
        }
        #endregion
        #region 私有
        public string ServiceName => "GFS";
        /// <summary>
        /// 美元对英镑汇率（临时写死.2020/12/31）
        /// </summary>
        private decimal usdTogbpRate = 0.73294m;
        private void OrderModelJudge(Order_Order order)
        {
            if (order.ReceiverCountryCode == "FR")
            {
                order.ReceiverCity = FixFRCity(order.ReceiverCity);
            }
            CheckAddress(order);

            if (!string.IsNullOrWhiteSpace(order.ReceiverState))
            {
                order.ReceiverState = order.ReceiverState.Trim();
            }
            if (!string.IsNullOrWhiteSpace(order.ReceiverCity))
            {
                order.ReceiverCity = order.ReceiverCity.Trim();
            }
            if (!string.IsNullOrWhiteSpace(order.ReceiverStreet))
            {
                order.ReceiverStreet = order.ReceiverStreet.Trim();
            }
        }
        private static string FixFRCity(string city)
        {

            if (!string.IsNullOrWhiteSpace(city))
            {
                city = city.ToUpper();

                if (city.StartsWith("SAINTE "))
                {
                    city = city.Replace("SAINTE ", "STE ");
                }
                else if (city.StartsWith("SAINT "))
                {
                    city = city.Replace("SAINT ", "ST ");
                }

                if (city.Contains("-"))
                {
                    city = city.Replace("-", " ");
                }
            }
            return city;
        }
        public void CheckAddress(Order_Order order)
        {

            if (order.ChannelId == 99)
            {
                var frList2 = _orderApiDeclarationRepository.GetFRSLAreas();
                if (frList2.Any(x =>
              x.Intercept &&
       !string.IsNullOrEmpty(x.AreaName) && x.AreaName.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)
       && !string.IsNullOrEmpty(x.ZipCode) && x.ZipCode.Equals(order.ReceiverZipCode, StringComparison.CurrentCultureIgnoreCase)
       ))
                {
                    //法运拦截
                    throw new Exception("法国该地区停止服务");
                }
                else
                {
                    var frArea = frList2.FirstOrDefault(x =>
                            !x.Intercept &&
                            !string.IsNullOrEmpty(x.AreaName) && x.AreaName.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)
                            && !string.IsNullOrEmpty(x.ZipCode) && x.ZipCode.Equals(order.ReceiverZipCode, StringComparison.CurrentCultureIgnoreCase)
                        );
                    if (
                        !frList2.Any(x =>
                            !x.Intercept &&
                            !string.IsNullOrEmpty(x.AreaName) && x.AreaName.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)
                            && !string.IsNullOrEmpty(x.ZipCode) && x.ZipCode.Equals(order.ReceiverZipCode, StringComparison.CurrentCultureIgnoreCase)
                        ))
                    {
                        //非正常地址出，法运中性面单 
                        throw new Exception("法国专线邮编、城市未对应");
                    }

                }
            }

        }
        private CreateOrderParam GetCreateOrderParam(Order_Order order, List<Order_OrderGoods> orderGoods, Logistics_Channel channel)
        {
            //法国渠道需要校验手机号码规则，并且
            if (order.ReceiverCountryCode.ToUpper() == "FR")
            {
                string phoneNumber = order.ReceiverPhone?.Trim();
                if (string.IsNullOrWhiteSpace(order?.ReceiverPhone))
                {
                    order.ReceiverPhone = "0612345678";
                }
                bool phoneNumberOk = ValidateTelephone(phoneNumber);
                if (!phoneNumberOk)
                {
                    order.ReceiverStreet += $" Tel:{order.ReceiverPhone}";
                    order.ReceiverPhone = "0612345678";
                    //throw new Exception("收件人手机号码不符合格式要求（法国手机号码为06/07/+336/+3306开头8位数字）");
                }
            }

            ///英国的邮编需要进行检查矫正
            if (order.ReceiverCountryCode.ToUpper() == "GB")
            {
                order.ReceiverZipCode = CorrectGBZipCode(order.ReceiverZipCode);
                if (string.IsNullOrEmpty(order.ReceiverState))
                {
                    //收件人州名不存在时，自动使用城市名补充
                    order.ReceiverState = order.ReceiverCity;
                }
            }


            CreateOrderParam param = new CreateOrderParam();
            string[] receiveryAddress = order.ReceiverStreet.Replace("|", "").ToArray(34);
            if (receiveryAddress.Count() > 2)
                throw new Exception("收件人地址超长");

            param.Consignee = new Consignee
            {
                consignee_city = order.ReceiverCity,
                consignee_name = order.ReceiverName,
                consignee_postcode = order.ReceiverZipCode.Trim(),
                consignee_province = order.ReceiverState,
                consignee_street = receiveryAddress[0],
                consignee_street2 = receiveryAddress.Length > 1 ? receiveryAddress[1] : string.Empty,
                consignee_telephone = order.ReceiverPhone,
            };
            param.country_code = order.ReceiverCountryCode;
            param.ItemArr = new List<ItemArrItem>();

            int totalQty = orderGoods.Sum(g => g.Quantity);

            var oriOrderGoods = orderGoods;
            orderGoods = orderGoods.CopyList<Order_OrderGoods>().ToList();
            SetOPGoodsValues(order, orderGoods, oriOrderGoods);

            decimal totalValue = orderGoods.Sum(g => g.Quantity * g.DeclareFee);
            if (orderGoods.Any(x => x.Weight == 0) || orderGoods.Sum(x => x.Weight * x.Quantity) > order.CustomerWeight)
            {
                int avgWeigh = (int)Math.Floor(order.CustomerWeight / (decimal)orderGoods.Sum(g => g.Quantity));
                orderGoods.ForEach(x => x.Weight = avgWeigh);
            }

            if (orderGoods != null && orderGoods.Count > 0)
            {
                foreach (var g in orderGoods)
                {
                    var goodsValue = GetUnitValue(channel.ServiceChannelCode, g.DeclareFee, totalQty, totalValue);

                    string sku = g.GoodsNumber;
                    if (order.ReceiverCountryCode == "CA" && order.CustomerId == 250)
                    {
                        sku = order.CustomerOrderNo;
                    }

                    ItemArrItem item = new ItemArrItem
                    {
                        hs_code = g.HsCode,
                        invoice_brand = null,
                        invoice_cnname = g.CnName,
                        invoice_enname = g.EnName,
                        invoice_quantity = g.Quantity.ToString(),
                        invoice_unitcharge = goodsValue.ToString(),
                        invoice_weight = (g.Weight / 1000.0).ToString("0.000"),
                        sku = sku
                    };
                    param.ItemArr.Add(item);
                }
            }
            param.order_pieces = 1;
            param.order_weight = order.CustomerWeight.KGFormat();
            param.POANumber = "";
            param.reference_id = "";
            param.reference_no = order.SystemNo + "_" + _order_OrderPrintQtyRepository.GetPackagePrintQty(order.SystemNo);
            param.shipment_id = "";
            param.Shipper = new Shipper
            {
                shipper_city = channel.SenderCity,
                shipper_countrycode = channel.SenderCountryCode,
                shipper_mobile = channel.SenderPhone,
                shipper_name = channel.SenderName,
                shipper_postcode = channel.SenderZipCode,
                shipper_province = channel.SenderState,
                shipper_street = channel.SenderStreet,
                shipper_telephone = channel.SenderPhone
            };
            param.shipping_method = channel.ServiceChannelCode;
            param.Volume = new List<VolumeItem> {
            new VolumeItem{
                child_number=null,
                weight=order.CustomerWeight.KGFormat(),
            }
            };

            return param;
        }
        private decimal GetUnitValue(string serviceCode, decimal currentGoodsValue, int totalQty, decimal totalValue)
        {
            decimal value = currentGoodsValue;
            if (serviceCode == "PK0055")//GB
            {
                value = currentGoodsValue * usdTogbpRate;
            }
            else if (serviceCode == "PK0088")//CA
            {
                //CA大于15USD的，要控制在15USD内
                if (totalValue >= 15m)
                {
                    value = 14.5m / totalQty;
                }
                else return currentGoodsValue;
            }

            return value;
        }
        /// <summary>
        /// 根据法邮要求，手机号码必须符合法国手机号码格式
        /// </summary>
        /// <param name="telephone"></param>
        private bool ValidateTelephone(string telephone)
        {
            if (string.IsNullOrWhiteSpace(telephone)) return false;
            telephone = telephone.Replace(" ", "");
            string phoneNumFormat = @"^(06|07|\+336|\+3306)\d{8}$";
            bool isMatch = System.Text.RegularExpressions.Regex.IsMatch(telephone, phoneNumFormat);
            return isMatch;
        }
        private string CorrectGBZipCode(string zipcode)
        {
            if (string.IsNullOrWhiteSpace(zipcode))
                throw new Exception("邮编不能为空");

            var cleanZip = zipcode.Replace(" ", "");

            if (cleanZip.Length < 4)
                throw new Exception("邮编格式不正确");
            else
            {
                int idx = cleanZip.Length - 3;
                cleanZip = cleanZip.Insert(idx, " ");
            }
            return cleanZip;
        }
        public void SetOPGoodsValues(Order_Order order, List<Order_OrderGoods> orderGoods, List<Order_OrderGoods> oriOrderGoods)
        {
            if (order.CustomerId == 1)
            {
                //先有订单后再下单时清理一次申报记录
                _orderApiDeclarationRepository.ExecuteSqlAsync($"delete Order_ApiDeclaration where systemno='{order.SystemNo}'");
                //澳鹏的做一次逻辑调整
                var r2 = new Random();
                Random random = new Random();
                if (orderGoods.Count > 1)
                {
                    do
                    {
                        int qty = orderGoods.Sum(x => x.Quantity);
                        decimal sumValue = random.Next(1000, 1450) / 100.00m;

                        //先取一次随机值
                        var avgValue = Math.Round(sumValue / (decimal)qty, 2);

                        foreach (var o in orderGoods)
                        {
                            decimal randomAS = 0 - (r2.Next(0, 50) / 100.00m);
                            o.DeclareFee = avgValue + randomAS;
                            if (o.EnName.Equals("coat", StringComparison.OrdinalIgnoreCase))
                            {
                                o.EnName = "shirt";
                            }
                            o.Guid = Guid.NewGuid().ToString();
                        }

                    }
                    //如果取随机数小于10时或大于14.5时，我们再随机几次，直至大于10USD
                    while (orderGoods.Sum(x => x.DeclareFee * x.Quantity) < 10.00m || orderGoods.Sum(x => x.DeclareFee * x.Quantity) > 14.5m);
                }
                for (int i = 0; i < orderGoods.Count; i++)
                {
                    oriOrderGoods[i].Guid = orderGoods[i].Guid;
                }
                _orderApiDeclarationRepository.BulkToDBAsync(orderGoods.Select(x => new Order_ApiDeclaration
                {
                    GoodsId=x.Id,
                    OriginDeclareFee=x.DeclareFee,
                    ChannelId = order.ChannelId,
                    OrderDeclareValue = orderGoods.Sum(y => y.DeclareFee * y.Quantity),
                    CnName = x.CnName,
                    EnName = x.EnName,
                    DeclareValue = x.DeclareFee,
                    SystemNo = order.SystemNo,
                    CreateTime = DateTime.Now,
                    CreateUserName = string.Empty,
                    Guid = x.Guid
                }).ToList());
            }
        }
        #endregion
        #region 实现接口

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

        public void CannelOrders(List<string> systemNO)
        {
            throw new NotImplementedException();
        }
        public void CannelOrdersByModel(logistics_ChannelCancel model)
        {
            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)
        {
            OrderModelJudge(order);
            try
            {
                var param = GetCreateOrderParam(order, goods, channel);
                string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);

                string service = "createOrder";
                string appToken = channel.ApiKey;
                string appKey = channel.ApiSecret;
                gfsbiz.EcClient ecClient = new gfsbiz.EcClient();
                //代理设置
                var b = ecClient.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
                FiddlerClient.SetProxy(b);

                string resultStr = ecClient.callServiceAsync(jsonParam, appToken, appKey, null, null, service).Result.Body.response;
                if (string.IsNullOrWhiteSpace(resultStr))
                    throw new Exception("服务返回结果为空");

                CreateOrderResult result = Newtonsoft.Json.JsonConvert.DeserializeObject<CreateOrderResult>(resultStr);
                if (result == null)
                    throw new Exception("创建订单结果反序列化失败");

                if (result.ask == "Success")
                {
                    var uploadResult = new UploadResult
                    {
                        DownloadUrl = null,
                        Error = null,
                        IsSuccess = true,
                        IsTransfer = false,
                        ResponseContent = resultStr,
                        ServiceOrderNumber = result.order_code,
                        ServiceOrderNumber2 = param.reference_no,
                        ServiceOrderNumber3 = null,
                        ServierFee = 0,
                        TrackingNumber = result.shipping_method_no,
                        TransferNumner = "",

                    };
                    return uploadResult;
                }
                else
                {
                    throw new Exception(result.message + result.Error != null ? ($"详细原因：{ result.Error.errMessage }({ result.Error.errCode})") : string.Empty);
                    var uploadResult = new UploadResult
                    {
                        Error = result.message + result.Error != null ? ($"详细原因：{result.Error.errMessage}({result.Error.errCode})") : string.Empty,
                        IsSuccess = false,
                    };
                    return uploadResult;
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
                var uploadResult = new UploadResult
                {
                    Error = ex.Message,
                    IsSuccess = false,
                };
                return uploadResult;
            }
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            GetLabelParam param = new GetLabelParam
            {
                label_type = "1",
                label_content_type = "1",
                reference_no = result.ServiceOrderNumber
            };
            string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);

            string service = "getLabelUrl";
            string appToken = channel.ApiKey;
            string appKey = channel.ApiSecret;
            gfsbiz.EcClient ecClient = new gfsbiz.EcClient();
            //代理设置
            var b = ecClient.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
            FiddlerClient.SetProxy(b);

            //渠道接口返回数据格式，当success时，error对象为数组，但failure时却为对象，所以要区分处理
            string resultStr = ecClient.callServiceAsync(jsonParam, appToken, appKey, null, null, service).Result.Body.response;
            if (resultStr.IndexOf("\"ask\":\"Failure\"") > 0)
            {
                ResultBase failureResult = Newtonsoft.Json.JsonConvert.DeserializeObject<ResultBase>(resultStr);
                string msg = "无返回错误信息";
                if (failureResult.Error != null && !string.IsNullOrEmpty(failureResult.Error.errMessage))
                    msg = failureResult.Error.errMessage;
                throw new Exception($"获取面单错误:{msg}");
            }

            GetLabelResult getLabelResult = Newtonsoft.Json.JsonConvert.DeserializeObject<GetLabelResult>(resultStr);
            if (getLabelResult.type == "pdf" && !string.IsNullOrWhiteSpace(getLabelResult.url))
            {
                System.Net.WebClient client = new System.Net.WebClient();
                try
                {
                    var data = client.DownloadData(getLabelResult.url);
                    string transferTag = string.Empty;
                    int waterMarkX = 120;//英国渠道的面单中标记靠左
                    int waterMarkY = 50;
                    int fontSize = 25;
                    if (order.ChannelId != 229 && order.ChannelId != 268 && (order.CreateOrderChannelId == 75 || order.CreateOrderChannelId == 98))
                        transferTag = "K";//空运
                    else if (order.CreateOrderChannelId == 99 || order.CreateOrderChannelId == 19)
                    {
                        transferTag = "K";//空运
                        waterMarkX = 240;//法国渠道面单的位置要靠右
                    }
                    else if (order.CreateOrderChannelId == 94)
                        transferTag = "T";//铁路
                    else if (order.CreateOrderChannelId == 95)
                    {
                        transferTag = "T";//铁路
                        waterMarkX = 240;
                    }
                    else if (order.ChannelId == 186)
                    {
                        transferTag = "B";
                        waterMarkX = 260;
                        waterMarkY = 2;
                        fontSize = 12;
                    }

                    if (transferTag != string.Empty)
                        data = PDFHelper.Watermark(data, transferTag, 1, waterMarkX, waterMarkY, fontSize, iTextSharp.text.BaseColor.BLACK);

                    if ((order.CreateOrderChannelId == 75 && order.ChannelId != 229 && order.ChannelId != 268) || order.CreateOrderChannelId == 94 || order.CreateOrderChannelId == 98 || order.CreateOrderChannelId == 102)
                    {
                        data = PDFHelper.Watermark(data, "Customers MUST NOT return to above address", 1, 100, 90, 9, iTextSharp.text.BaseColor.BLACK);
                        data = PDFHelper.Watermark(data, order.CustomerOrderNo, 1, 10, 10, 9, iTextSharp.text.BaseColor.BLACK);
                    }
                    return data;
                }
                catch (Exception ex)
                {
                    throw new Exception($"下载面单失败:{ex.Message}");
                }
            }
            else
            {
                string msg = "无错误信息";
                if (getLabelResult.Error != null)
                    msg = getLabelResult.Error.errMessage;

                throw new Exception($"面单结果无效:{msg},type:{getLabelResult.type},url:{getLabelResult.url}");
            }
        }

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