using Microsoft.Extensions.Logging;
using SSD_USPS;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.ExtendMethods;
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.AddressHelper;
using XYY.Service.Standard.ChannelApi.Base;

namespace XYY.Service.Standard.ChannelApi.SSD_USPS
{
    /// <summary>
    /// 深速度。文档地址：http://ec.wiki.eccang.com/docs/show/827
    /// </summary>
    public class Api : IBaseApi
    {
        ILogger<Api> _logger;
        IOrder_OrderPrintQtyRepository _orderPrintQtyRepository;
        IOrderRepository _orderRepository;

        public Api(ILogger<Api> logger, IOrder_OrderPrintQtyRepository orderPrintQtyRepository, IOrderRepository orderRepository)
        {
            _orderPrintQtyRepository = orderPrintQtyRepository;
            _logger = logger;
            _orderRepository = orderRepository;
        }

        public int MaxBatchGrabCount => 100;

        public string ServiceName => "SSD_FC";

        private CreateOrderParam GetCreateOrderParam(Order_Order order, List<Order_OrderGoods> orderGoods, Logistics_Channel channel)
        {

            CreateOrderParam param = new CreateOrderParam();

            string originAddress = order.ReceiverStreet.Replace("|", "");
            string[] receiveryAddress = originAddress.ToArray(35);
            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);
            decimal totalValue = orderGoods.Sum(g => g.Quantity * g.DeclareFee);

            int orderWeight = channel.IsTransfer && order.OPWeight > 0 ? order.OPWeight : order.CustomerWeight;
            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;
                    }

                    int goodsWeight = g.Weight;
                    if (goodsWeight <= 0)
                    {
                        goodsWeight = (int)Math.Ceiling(((decimal)orderWeight / orderGoods.Count));
                    }

                    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("0.00"),
                        invoice_weight = (goodsWeight / 1000m).ToString("0.000"),
                        sku = sku
                    };
                    param.ItemArr.Add(item);
                }
            }



            param.order_pieces = 1;
            param.order_weight = orderWeight.KGFormat();
            param.POANumber = "";
            param.reference_id = "";
            param.reference_no = order.SystemNo;
            //if (order.CustomerId == 197 || order.CustomerId == 294)
            //{
            //    param.reference_no = order.CustomerOrderNo;
            //}
            //else
            //{
            //    param.reference_no = order.TransferNumber;
            //}
            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.shipping_method = "SSD-OMPH";
            param.Volume = new List<VolumeItem> {
            new VolumeItem{
                child_number=null,
                weight=orderWeight.KGFormat(),
            }
            };

            return param;
        }

        public async Task<string> CreateOrderByApi(Order_Order order, List<Order_OrderGoods> orderGoods, Logistics_Channel channel)
        {

            if (order.CustomerWeight > 2260 && channel.PublicName == "SSD-PM")
            {
                throw new Exception("超出渠道限制");
            }

            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();
            }

            if (order.ReceiverPhone.Contains("US_1-"))//细刻很多这种开头
            {
                order.ReceiverPhone = order.ReceiverPhone.Replace("US_1-", "");
            }
            if (string.IsNullOrWhiteSpace(order.ReceiverPhone))
            {
                order.ReceiverPhone = "123456";
            }
            //SSD的正则规则
            if (!System.Text.RegularExpressions.Regex.IsMatch(order.ReceiverPhone, @"^[0-9-\(\)+ ext.EXT]{1,30}$"))
            {
                throw new Exception("无效的美国电话号码格式");
            }

            USAddressCheck addressCheck = new USAddressCheck();
            addressCheck.CheckUSOrder(order);

            var param = GetCreateOrderParam(order, orderGoods, channel);
            string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);

            string service = "createOrder";
            string appToken = channel.ApiKey;
            string appKey = channel.ApiSecret;
            string customerId = null;
            string customerCode = null;

            EcClient ecClient = new EcClient();
            //代理设置
            var b = ecClient.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
            FiddlerClient.SetProxy(b);

            var createOrderResp = await ecClient.callServiceAsync(jsonParam, appToken, appKey, customerId, customerCode, null, service);
            string resultStr = createOrderResp?.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")
            {
                if (!string.IsNullOrWhiteSpace(result.order_code))
                    return result.order_code;
                else
                {
                    throw new Exception($"渠道单号为空");
                }
            }
            else
            {
                if (!string.IsNullOrWhiteSpace(result?.Error?.errMessage))
                {
                    throw new Exception($"{result.message},{result.Error?.errMessage} {result.Error?.errCode}");
                }
                else
                {
                    throw new Exception($"渠道下单失败,未知错误");
                }
            }
        }



        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> orderGoods, Logistics_Channel channel, ExtendArg arg)
        {

            string channelOrderCode = null;
            string errorMessage = null;

            string number = order.SystemNo;
            if (order.CustomerId == 197 || order.CustomerId == 294)
            {
                number = order.CustomerOrderNo;
            }
            var channelOrderId = await _orderRepository.GetChannelOrderInfoRecord(channel.Id, number);
            if (!string.IsNullOrEmpty(channelOrderId))
            {
                channelOrderCode = channelOrderId;
            }
            else
            {
                try
                {
                    string order_code = await CreateOrderByApi(order, orderGoods, channel);
                    if (!string.IsNullOrEmpty(order_code))
                    {
                        await _orderRepository.AddChannelOrderInfoRecord(channel.Id, order_code, number);
                    }
                    else
                    {
                        errorMessage = "获取不到渠道商单号";
                    }
                }
                catch (Exception ex)
                {
                    errorMessage = ex.Message;
                }
            }

            if (string.IsNullOrWhiteSpace(errorMessage) || errorMessage.Contains("参考单号已存在"))
            {


                bool onlineSendOrder = order.TransferNumber.StartsWith("AQ") && order.TransferNumber.EndsWith("CN");
                string transferNumber = number;
                if (order.CustomerId == 197 || order.CustomerId == 294)
                {
                    return new UploadResult
                    {
                        DownloadUrl = null,
                        IsSuccess = true,
                        TrackingNumber = order.SystemNo,
                        ServiceOrderNumber = channelOrderCode
                    };
                }
                string trackNo = await RetryGetTrackingNumber(transferNumber, channel);


                //string trackNo = await RetryGetTrackingNumber(number, channel);

                var labelResult = await RetryGetLabel(trackNo, channel);
                if (!string.IsNullOrWhiteSpace(labelResult?.url))
                {
                    return new UploadResult
                    {
                        DownloadUrl = labelResult.url,
                        IsSuccess = true,
                        TrackingNumber = trackNo,
                        ServiceOrderNumber = channelOrderCode
                    };
                }
                else
                {
                    if (!string.IsNullOrWhiteSpace(labelResult?.Error?.errMessage))
                    {
                        throw new Exception($"{labelResult.Error.errMessage},{labelResult.Error.errCode}");
                    }
                    else throw new Exception("渠道返回面单地址为空");
                }
            }
            else
            {
                throw new Exception(errorMessage);
            }
        }

        private async Task<GetLabelResult> RetryGetLabel(string trackingNo, Logistics_Channel channel)
        {
            int retryCount = 1;
            int interval = 10 * 1000;
            GetLabelResult result = null;
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    result = await GetLabel(trackingNo, channel);
                }
                catch (Exception ex)
                {
                    if (i >= retryCount)
                        throw;
                }
                if (!string.IsNullOrWhiteSpace(result?.url))
                    return result;
                else
                {
                    System.Threading.Thread.Sleep(interval);
                }
            }
            throw new Exception($"获取面单API错误:重试{retryCount}次仍不能获取面单");

        }

        private async Task<string> RetryGetTrackingNumber(string transferNumber, Logistics_Channel channel)
        {
            int retryCount = 1;
            int interval = 10 * 1000;
            string trackingNumber = null;
            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    trackingNumber = await GetTrackingNumber(transferNumber, channel);
                }
                catch (Exception ex)
                {
                    if (i >= retryCount || ex.Message.Contains(""))
                        throw;
                }
                if (!string.IsNullOrWhiteSpace(trackingNumber))
                    return trackingNumber;
                else
                {
                    System.Threading.Thread.Sleep(interval);
                }
            }
            throw new Exception($"获取跟踪号API错误:重试{retryCount}次仍不能获取跟踪号");

        }

        private async Task<string> GetTrackingNumber(string transferNumber, Logistics_Channel channel)
        {
            try
            {


                GetTrackNumberRequest param = new GetTrackNumberRequest
                {
                    reference_no = new List<string> { transferNumber }
                };
                string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);
                string appToken = channel.ApiKey;
                string appKey = channel.ApiSecret;

                EcClient client1 = new EcClient();
                //代理设置
                var b = client1.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
                FiddlerClient.SetProxy(b);

                var resp = await client1.callServiceAsync(jsonParam, appToken, appKey, null, null, null, "getTrackNumber");
                var respStr = resp?.Body?.response;
                if (string.IsNullOrWhiteSpace(respStr))
                {
                    throw new Exception("获取跟踪号API错误:获取面单响应为空");
                }
                else
                {


                    GetTrackNumberResult result = Newtonsoft.Json.JsonConvert.DeserializeObject<GetTrackNumberResult>(respStr);
                    if (result == null)
                    {
                        throw new Exception("获取跟踪号API错误:获取跟踪号响应解释错误");
                    }
                    if (result.ask == "Success")
                    {
                        string trackingNumber = result.data?.FirstOrDefault()?.TrackingNumber;
                        if (string.IsNullOrWhiteSpace(trackingNumber))
                        {
                            throw new Exception("获取跟踪号API错误:获取的跟踪号为空");
                        }
                        else return trackingNumber;
                    }
                    else
                    {
                        if (result.Error is Newtonsoft.Json.Linq.JObject)
                        {
                            string json = result.Error.ToString();
                            if (json.Contains("订单信息不存在"))
                            {
                                throw new Exception(json);
                            }
                        }
                        throw new Exception($"获取跟踪号API错误:{result.message}");
                        //if (!string.IsNullOrWhiteSpace(result?.Error?.errMessage))
                        //{
                        //    throw new Exception($"获取面单API错误:{result.Error.errMessage},{result.Error.errCode}");
                        //}
                        //else throw new Exception($"获取面单API错误:{result.message}");
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"获取跟踪号API错误:{ex.Message}");
            }
        }


        private async Task<GetLabelResult> GetLabel(string trackingNo, Logistics_Channel channel)
        {
            try
            {
                GetLabelParam param = new GetLabelParam
                {
                    label_type = 3,
                    label_content_type = 1,
                    reference_no = trackingNo,
                    type = 3
                };
                string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);

                string service = "getLabelUrl";
                string appToken = channel.ApiKey;
                string appKey = channel.ApiSecret;
                string customerId = null;
                string customerCode = null;

                EcClient ecClient = new EcClient();
                //代理设置
                var b = ecClient.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
                FiddlerClient.SetProxy(b);

                //渠道接口返回数据格式，当success时，error对象为数组，但failure时却为对象，所以要区分处理
                var createLabelResult = await ecClient.callServiceAsync(jsonParam, appToken, appKey, customerId, customerCode, null, service);
                string resultStr = createLabelResult?.Body?.response;
                if (string.IsNullOrWhiteSpace(resultStr))
                {
                    throw new Exception("获取面单响应为空");
                }

                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);
                return getLabelResult;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取面单API错误:{ex.Message}");
            }
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            if (result.TrackingNumber.StartsWith("XYY"))
            {
                string trackNo = await RetryGetTrackingNumber(order.CustomerOrderNo, channel);
                var labelResult = await RetryGetLabel(trackNo, channel);
                result.DownloadUrl = labelResult.url;
                result.TrackingNumber = trackNo;
            }

            int minSize = 5 * 1024;
            byte[] data = null;
            for (var i = 0; i < 3; i++)
            {
                try
                {
                    data = await new System.Net.WebClient().DownloadDataTaskAsync(result.DownloadUrl);
                    if (data.Length >= minSize)
                        return data;
                }
                catch
                {

                }
            }
            if (data == null)
            {
                throw new Exception("标签信息有误请联系IT");
            }
            else if (data.Length < minSize)
            {
                throw new Exception("标签内容过小请联系IT");
            }
            else
            {
                return data;
            }

        }

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

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

        private decimal GetUnitValue(string serviceCode, decimal currentGoodsValue, int totalQty, decimal totalValue)
        {
            decimal value = currentGoodsValue;

            return value;
        }

        //public static 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;
        //}

        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();
        }
    }
}

