using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using XYY.Common.Standard.String;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Data.Standard.Order;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using Dapper;
using System.Text.RegularExpressions;
using XYY.Core.Standard.ExtendMethods;

namespace XYY.Service.Standard.ChannelApi.Winit.ISPApi
{

    public partial class ISPApi : IBaseApi
    {
        private IUnitOfWork _unitOfWork;
        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        readonly IOrderRepository _orderRepository;
        readonly IOrderApiDeclarationRepository apiDeclarationRepository;

        public ISPApi(IOrderRepository orderRepository, IOrderApiDeclarationRepository apiDeclarationRepository, IUnitOfWork unitOfWork)
        {
            _orderRepository = orderRepository;
            this.apiDeclarationRepository = apiDeclarationRepository;
            _unitOfWork = unitOfWork;
        }


        public string ServiceName => "WinitISP";

        string[] transferNumbers = new string[]
        {
            "XYYEX0026237628YQ","XYYEX0026241372YQ"
        };

        public static bool IsPOBox(string address)
        {
            bool isPoBox = Regex.IsMatch(address, @"(?i)\b(?:p\.?\s*o\.?|post\s+office)(\s+)?(?:box|[0-9]*)?\b", RegexOptions.IgnoreCase);
            return isPoBox;
        }
        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {

            string refNo = order.SystemNo;

            int[] channeldIds = new int[] { 221, 222, 223 };

            if (transferNumbers.Contains(order.TransferNumber))
            {
                refNo = refNo.Replace("XYYEX", "R");
            }

            if (order.ChannelId == 372)
            {
                if (order.ReceiverZipCode == "27498" || order.ReceiverZipCode == "78266")
                {
                    throw new Exception("德国DHL不支持以下邮编27498、78266");
                }

                if (IsPOBox(order.ReceiverStreet))
                {
                    throw new Exception("德国DHL不支持以下PO BOX地址");
                }

                var goodsfee = goods.Sum(x => x.DeclareFee * x.Quantity);
                //全部为欧元
                bool isChange = false;
                if (goods.Where(x => x.DeclareCurrency == "EUR").Count() == goods.Count)
                {
                    if (goodsfee < 25)
                    {
                        isChange = true;
                        var avg = Math.Ceiling(25 / (decimal)goods.Sum(x => x.Quantity) * 100) / 100;
                        goods.ForEach(x => x.DeclareFee = avg);
                    }

                    goods.ForEach(x => x.DeclareFee *= 1.1m);
                }
                else if (goods.Where(x => x.DeclareCurrency == "USD").Count() == goods.Count)
                {
                    if (goodsfee < 25 * 1.1m)
                    {
                        isChange = true;
                        var avg = Math.Ceiling(25 * 1.1m / (decimal)goods.Sum(x => x.Quantity) * 100) / 100;
                        goods.ForEach(x => x.DeclareFee = avg);
                    }
                }
                else
                {
                    throw new Exception("请传入一致的币种，EUR或USD");
                }

                if (isChange)
                {
                    var model = goods.Select(x => new Order_ApiDeclaration
                    {
                        GoodsId = x.Id,
                        OriginDeclareFee = x.DeclareFee,
                        ChannelId = 0,
                        OrderDeclareValue = goods.Sum(y => y.DeclareFee * y.Quantity),
                        CnName = x.CnName,
                        EnName = x.EnName,
                        DeclareValue = x.DeclareFee,
                        SubmitDeclareValue = x.DeclareFee,
                        SystemNo = order.SystemNo,
                        CreateTime = DateTime.Now,
                        CreateUserName = string.Empty,
                        Guid = x.Guid,
                        Qty = x.Quantity
                    }).ToList();

                    var list = await _unitOfWork.QueryAsync<Order_ApiDeclaration>(x => x.SystemNo == order.SystemNo);
                    var ids = list?.Select(i => i.Id);
                    if (ids?.Any() == true)
                    {
                        await _unitOfWork.ExecuteAsync($"delete Order_ApiDeclaration where id in @ids", new { ids = ids });
                    }
                    await _unitOfWork.BulkToDBAsync<Order_ApiDeclaration>(model);
                }
            }

            if (channeldIds.Contains(order.ChannelId))
            {
                refNo = refNo.Replace("XYYEX", "A");
                //电话处理、电话大于20位时，我们做一个字符替换处理
                if (!string.IsNullOrEmpty(order.ReceiverPhone) && order.ReceiverPhone.Length > 20)
                {
                    order.ReceiverPhone = order.ReceiverPhone.Replace("+", "").Replace("-", "").Replace(" ", "");
                }
            }
            if (order.CustomerId == 294 || order.CustomerId == 301)
            {
                //河南邮政的，我们使用客户单号作下单记录
                refNo = order.CustomerOrderNo;
            }
            Result<OrderResult> r = null;
            var winitOrder = await _orderRepository.GetWinitOrderNo(refNo);
            if (!string.IsNullOrEmpty(winitOrder))
            {
                winitOrder = winitOrder.Trim('\t');
                r = new Result<OrderResult>
                {
                    msg = "操作成功",
                    data = new OrderResult
                    {
                        orderNo = winitOrder
                    }
                };
            }
            else
            {
                var o = ConvertOrder(order, goods, channel);
                r = await Send<OrderResult, OrderInfo>(
                   "isp.order.createOrder", o);
                if (r.msg == "操作成功")
                    await _orderRepository.AddWinitLog(r.data.orderNo, refNo);
            }
            if (r.msg == "操作成功")
            {
                var l = new LabelRequest { orderNo = r.data.orderNo };

                var rl = await Send<LabelResult, LabelRequest>("winitLable.query", l);
                if (rl.msg == "操作成功")
                {
                    return new UploadResult
                    {
                        IsTransfer = false,
                        IsSuccess = true,
                        TrackingNumber = r.data.trackingNo ?? rl.data.trackingNo[0],
                        ServiceOrderNumber = r.data.orderNo,
                        DownloadUrl = rl.data.files[0]
                    };
                }
                else
                {
                    throw new Exception(rl.msg);
                }
            }
            else
            {
                throw new Exception(r.msg);
            }
        }

        public async Task<string> GetData()
        {
            var response = await Send<dynamic, dynamic>("sms.incomeSettlement.pageChargeDetails",
                new
                {
                    deducationTimeStart = "2021-03-15",
                    deducationTimeEnd = "2021-03-16",
                    pageParams = new
                    {
                        pageNo = 1,
                        pageSize = 100
                    }
                }
                );
            return "";
        }

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

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

        public OrderInfo ConvertOrder(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            string refNo = order.SystemNo;
            int[] channeldIds = new int[] { 221, 222, 223, 403, 410 };
            if (transferNumbers.Contains(order.TransferNumber))
            {
                refNo = refNo.Replace("XYYEX", "R");
            }

            if (channeldIds.Contains(order.ChannelId))
            {
                refNo = refNo.Replace("XYYEX", "A");
            }


            if (channeldIds.Contains(order.ChannelId))
            {
                if (order.CustomerId == 302)
                {
                    if (order.ReceiverPhone.Length > 20)
                    {
                        order.ReceiverPhone = order.ReceiverPhone.Replace(" ", "").Replace("+", "").Replace("-", "").Replace("_", "");
                    }
                }
            }
            string street = order.ReceiverStreet;
            string house = order.House;
            if (order.ReceiverCountryCode == "US")
            {
                string[] Remote = new string[] { "AK", "HI", "GU", "AS", "MP", "PR", "VI", "AE", "AP" };

                Dictionary<string, string> pairs = new Dictionary<string, string>
                {
                    { "Washington", "WA" },
                    { "Oregon", "OR" },
                    { "California", "CA" },
                    { "Nevada", "NV" },
                    { "Idaho", "ID" },
                    { "Utah", "UT" },
                    { "Arizona", "AZ" },
                    { "Montana", "MT" },
                    { "Wyoming", "WY" },
                    { "Colorado", "CO" },
                    { "New Mexico", "NM" },
                    { "Wisconsin", "WI" },
                    { "Illinois", "IL" },
                    { "Tennessee", "TN" },
                    { "Mississippi", "MS" },
                    { "Michigan", "MI" },
                    { "Indiana", "IN" },
                    { "Kentucky", "KY" },
                    { "Alabama", "AL" },
                    { "Ohio", "OH" },
                    { "West Virginia", "WV" },
                    { "Virginia", "VA" },
                    { "North Carolina", "NC" },
                    { "South Carolina", "SC" },
                    { "Georgia", "GA" },
                    { "North Dakota", "ND" },
                    { "South Dakota", "SD" },
                    { "Nebraska", "NE" },
                    { "Kansas", "KS" },
                    { "Oklahoma", "OK" },
                    { "Texas", "TX" },
                    { "Minnesota", "MN" },
                    { "Iowa", "IA" },
                    { "Missouri", "MO" },
                    { "Arkansas", "AR" },
                    { "Louisiana", "LA" },
                    { "Florida", "FL" },
                    { "Pennsylvania", "PA" },
                    { "New York", "NY" },
                    { "Washington D. C.", "DC" },
                    { "Maryland", "MD" },
                    { "Delaware", "DE" },
                    { "New Jersey", "NJ" },
                    { "Connecticut", "CT" },
                    { "Rhode Island", "RI" },
                    { "Massachusetts", "MA" },
                    { "Maine", "ME" },
                    { "New Hampshire", "NH" },
                    { "Vermont", "VT" }
                };

                if (!pairs.Keys.Any(x => x.Equals(order.ReceiverState, StringComparison.CurrentCultureIgnoreCase))
                        && !pairs.Values.Any(x => x.Equals(order.ReceiverState, StringComparison.CurrentCultureIgnoreCase))
                        )
                {
                    if (pairs.Keys.Any(x => x.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)))
                    {
                        string state = order.ReceiverState;
                        order.ReceiverState = pairs.Where(x => x.Key.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)).First().Value;
                        order.ReceiverCity = state;
                    }
                    else if (pairs.Values.Any(x => x.Equals(order.ReceiverCity, StringComparison.CurrentCultureIgnoreCase)))
                    {
                        string state = order.ReceiverState;
                        order.ReceiverState = order.ReceiverCity;
                        order.ReceiverCity = order.ReceiverState;
                    }
                    else
                    {
                        throw new Exception("美国专线必须传入标准的州名或州简写");
                    }
                }
                else if (pairs.Keys.Any(x => x.Equals(order.ReceiverState, StringComparison.CurrentCultureIgnoreCase)))
                {
                    order.ReceiverState = pairs.Where(x => x.Key.Equals(order.ReceiverState, StringComparison.CurrentCultureIgnoreCase)).First().Value;
                }
                if (Remote.Any(x => x.Equals(order.ReceiverState, StringComparison.CurrentCultureIgnoreCase)))
                {
                    throw new Exception("美国该地区不支持派送");
                }
            }
            else if (order.ReceiverCountryCode == "DE")
            {
                if (string.IsNullOrWhiteSpace(order.House))
                {
                    System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^.*?(?=\d)");
                    var match = regex.Match(order.ReceiverStreet);
                    if (!match.Success)
                    {
                        throw new Exception("德国专线地址内需要包含街道与数字门牌号");
                    }
                    else
                    {
                        house = regex.Replace(order.ReceiverStreet, "");
                        street = match.Value.Replace(",", " ");
                    }
                }
                else
                {
                    house = order.House;
                    street = order.ReceiverStreet;
                    //去掉门牌号重复的问题;
                    street = TrimEnd(street, house);
                }
            }
            string[] receiveryAddress = order.ReceiverStreet.Replace("|", "").ToArray(100);
            if (receiveryAddress.Length > 2)
                throw new Exception("地址超长");
            var postOrder = new OrderInfo
            {
                buyerAddress1 = receiveryAddress[0].Trim(),
                buyerAddress2 = receiveryAddress.Length == 2 ? receiveryAddress[1].Trim() : "",
                buyerCity = order.ReceiverCity,
                buyerCountry = order.ReceiverCountryCode,
                refNo = refNo,
                isAllowRepeat = "N",
                winitProductCode = "WP-MYP002",
                warehouseCode = "YW10000009",
                buyerState = order.ReceiverState,
                dispatchType = "T",
                shipperAddrCode = "114488",
                buyerContactNo = order.ReceiverPhone,
                buyerEmail = "",
                buyerHouseNo = order.House,
                buyerZipCode = order.ReceiverZipCode,
                packageList = new List<PackageListItem> { },
                pickUpCode = refNo,
                buyerName = order.ReceiverName
            };

            string[] keySplie = channel.ApiKey.Split(';');


            postOrder.winitProductCode = keySplie[0];
            postOrder.warehouseCode = keySplie[1];
            postOrder.dispatchType = "T";

            postOrder.shipperAddrCode = channel.ApiSecret;

            postOrder.packageList.Add(new PackageListItem
            {
                height = "0.10",
                length = "0.10",
                weight = (order.CustomerWeight / 1000.0).ToString("0.000"),
                width = "0.10",
                merchandiseList = new List<MerchandiseListItem>
                {

                }
            });
            if (channeldIds.Contains(order.ChannelId))
            {
                postOrder.packageList[0].length = "15.24";
                postOrder.packageList[0].width = "0.64";
                postOrder.packageList[0].height = "7.62";
            }
            postOrder.packageList[0].merchandiseList = goods.Select(x => new MerchandiseListItem
            {
                hsCode = x.HsCode,
                declaredNameCn = x.CnName,
                declaredNameEn = x.EnName,
                declaredValue = Math.Round(x.DeclareFee, 2).ToString("0.00"),
                merchandiseQuantity = x.Quantity.ToString(),
                merchandiseCode = x.GoodsNumber
            }).ToList();
            //postOrder.packageList[0].merchandiseList.First().merchandiseCode = goods.FirstOrDefault().GoodsNumber;

            return postOrder;
        }

        public string GetSign(string token, string actionValue, string app_keyValue, string dataValue,
            string formatValue, string platformValue, string sign_methodValue, string timestampValue,
            string versionValue)
        {
            string str = token + "action" + actionValue + "app_key" + app_keyValue + "data" + dataValue
                + "format" + formatValue + "platform" + platformValue + "sign_method"
                + sign_methodValue + "timestamp" + timestampValue
                + "version" + versionValue + token;
            return Encryption.Md532(str);
        }

        public string GetJson(object o)
        {
            string json = JsonConvert.SerializeObject(o);
            try
            {
                if (o.GetType().GetGenericTypeDefinition() == typeof(List<>))
                    return json;
            }
            catch
            {

            }
            var dic = JsonConvert.DeserializeObject<SortedDictionary<string, object>>(json);
            SortedDictionary<string, object> keyValues = new SortedDictionary<string, object>(dic);
            keyValues.OrderBy(m => m.Key);

            return JsonConvert.SerializeObject(keyValues);
        }

        public async Task<Result<T>> Send<T, T2>(
            string actionValue,
            T2 dataValue,
           string client_secret = "ZGJJYJA0YZYTYZDJZS00YWZJLTGZZWUTNJLJOTHKZTGXNDK2NTCZODM3NTCWMJC2MDA3MDM=",
           string clintId = "MWRMNGZKODYTYZHMNI00NZG0LWJKZWYTMMYZY2IZYZRIZDK1",
           string formatValue = "json",
           string platformValue = "xyy",
           string sign_methodValue = "md5",
           string versionValu = "1.0",
            string app_keyValue = "alice-xie@xingyunyi.cn",
            string token = "28BBD9FABE5696E814F06218E5C200CC",
             string url = "https://openapi.winit.com.cn/openapi/service",
             bool keyUp = true
           )
        {
            string timestampValue = DateTime.Now.ToString_yyyyMMddHHmmss();
            string strData = keyUp ? GetJson(dataValue) : Newtonsoft.Json.JsonConvert.SerializeObject(dataValue);

            string sign = GetSign(token, actionValue, app_keyValue
                , strData, formatValue, platformValue, sign_methodValue, timestampValue, versionValu).ToUpper();
            string client_sign = GetClient_Sign(client_secret, actionValue, app_keyValue, strData,
                formatValue, platformValue, sign_methodValue, timestampValue, versionValu).ToUpper();
            RequestOrder<T2> request = new RequestOrder<T2>
            {
                action = actionValue,
                data = dataValue,
                client_id = clintId,
                app_key = app_keyValue,
                format = formatValue,
                timestamp = timestampValue,
                language = "zh_CN",
                platform = platformValue,
                sign_method = sign_methodValue,
                version = versionValu,
                sign = sign,
                client_sign = client_sign
            };
            RestSharp.RestClient rest = new RestSharp.RestClient(url);
            rest.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            //rest.Proxy = new WebProxy("http://127.0.0.1:8888");
            RestSharp.RestRequest restRequest = new RestSharp.RestRequest(RestSharp.Method.POST);
            restRequest.AddJsonBody(request);
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(request);
            var response = await rest.ExecuteTaskAsync(restRequest);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return Newtonsoft.Json.JsonConvert.DeserializeObject<Result<T>>(response.Content);
            }
            else
            {
                throw new Exception(response.ErrorMessage ?? response.Content);
            }
        }

        public string GetClient_Sign(string client_secret, string actionValue, string app_keyValue, string dataValue,
            string formatValue, string platformValue, string sign_methodValue, string timestampValue, string versionValue
            )
        {
            string str2 = client_secret + "action" + actionValue + "app_key" + app_keyValue + "data" + dataValue
                + "format" + formatValue + "platform" + platformValue + "sign_method" + sign_methodValue
                + "timestamp" + timestampValue + "version" + versionValue + client_secret;
            return Encryption.Md532(str2);
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            string base64 = result.DownloadUrl;
            var bytes = Convert.FromBase64String(base64);
            return bytes;
        }

        public async Task<List<string>> Confims(List<OrderConfimRequest> order, Logistics_Channel channel)
        {
            var list = new List<string>();
            foreach (var item in order)
            {


                var cl = await Send<ConfirmResult, ISPConfirm>("isp.delivery.confirm",
              new ISPConfirm { orderNo = item.OrderNo });
                string message = cl.msg;
                if (message == "操作成功")
                {
                }
                else
                {
                    list.Add(item.OrderNo);
                }
            }
            return list;

        }

        public async Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {
            List<BagDeclareErrosResult> bagDeclareErrosResults = new List<BagDeclareErrosResult>();
            var list = new List<BagDeclareErrosResult>();
            int j = 0;
            foreach (var item in bagDeclareRequest.BatchDeclare.Values)
            {
                foreach (var i in item)
                {
                    try
                    {
                        j++;

                        Console.WriteLine(j.ToString() + "/" + bagDeclareRequest.BatchDeclare.Sum(x => x.Value.Count));
                        var cl = await Send<ConfirmResult, ISPConfirm>("isp.delivery.confirm",
                      new ISPConfirm { orderNo = i.ServiceNo });
                        string message = cl.msg;
                        if (message == "操作成功")
                        {
                        }
                        else
                        {
                            list.Add(new BagDeclareErrosResult { TrackingNumber = i.TrackingNumber, ErrorMessage = message });
                        }
                    }
                    catch (Exception ex)
                    {

                        list.Add(new BagDeclareErrosResult { TrackingNumber = i.TrackingNumber, ErrorMessage = ex.Message });
                    }
                }
            }
            return list;
        }

        public async void CannelOrders(List<string> systemNO)
        {
            await Send<dynamic, List<disableReq>>("isp.order.disable", systemNO.Select(x => new disableReq { orderNo = x }).ToList());
        }


        public class disableReq
        {
            public string orderNo { get; set; }
        }


        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            List<string> cannelOrderSystemNos = new List<string>() { logistics_ChannelCancel.SystemNo };
            var list =
                _orderRepository.QueryBySqlAsync("select * from Order_Order where SystemNo in @SystemNo", new { SystemNo = cannelOrderSystemNos }).Result;
            if (list != null)
            {
                var response = 
                      Send<dynamic, List<disableReq>>("isp.order.disable",
                      list.Select(x => new disableReq { orderNo = x.ServicesOrderNo }).ToList()).Result;

                string message = response.msg;
                logistics_ChannelCancel.ResultState = ResultStateEnum.成功.GetValue();
            }
        }
    }
}
