using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
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.Frayun.Model;

namespace XYY.Service.Standard.ChannelApi.Frayun
{
    public partial class Api : IBaseApi
    {
        #region 构造
        IOrderRepository _orderRepository;
        public Api(IOrderRepository orderRepository)
        {
            this._orderRepository = orderRepository;
        }
        #endregion
        #region 私有
        public string ServiceName => "Frayun";
        private void OrderModelJudge(Order_Order order, Logistics_Channel channel)
        {
            if (order.ReceiverCountryCode == "US")
            {

                if (string.IsNullOrWhiteSpace(order.ReceiverPhone))
                {
                    order.ReceiverPhone = "123456";
                }

                if (!string.IsNullOrWhiteSpace(order.ReceiverState))
                {
                    order.ReceiverState = order.ReceiverState.Trim();
                }

                if (!string.IsNullOrWhiteSpace(order.ReceiverCity))
                {
                    order.ReceiverCity = order.ReceiverCity.Trim();
                }

                ///直接截取前5位邮编
                if (order.ReceiverZipCode.Contains('-'))
                {
                    if (order.ChannelId == 123)
                        order.ReceiverZipCode = order.ReceiverZipCode.Split('-')[0];
                }

                if (!Regex.IsMatch(order.ReceiverZipCode, @"^[0-9]{5}(\-[0-9]{4})?$"))
                {
                    //if (order.ChannelId == 123)
                    throw new Exception("美国邮编格式错误");
                }

                //校验非英文字符
                string addressCharaterRegex = @"^[a-z0-9A-Z\ \,\.\#\-/]+$";//地址
                string nameCharaterRegex = @"^[a-z0-9A-Z\ \.\-\&]+$";
                //if(!Regex.IsMatch(order.ReceiverName, charaterRegex))
                //    throw new Exception("收件人姓名包含非英文字符");
                if (!Regex.IsMatch(order.ReceiverStreet, addressCharaterRegex))
                    throw new Exception("收件人街道包含非英文字符");
                if (!Regex.IsMatch(order.ReceiverCity, addressCharaterRegex))
                    throw new Exception("收件人城市包含非英文字符");
                if (!Regex.IsMatch(order.ReceiverName, nameCharaterRegex))
                    throw new Exception("收件人名字包含非法字符");

                order.CustomerOrderNo = order.CustomerOrderNo.Replace("_", "");
                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" },
                    {"Alaska","AK" },
                    {"Hawaii","HI" }
                };

                string[] Remote = new string[] { "AK", "HI", "GU", "AS", "MP", "PR", "VI", "AE", "AP" ,
                    "Guam", "Hawaii", "Alaska", "American Samoa" , "Eastern Samoa" ,"Northern Marianas","Puerto Rico","United States Virgin Islands"};

                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("美国该地区不支持派送");
                }
                if (!string.IsNullOrEmpty(order.House))
                {
                    order.ReceiverStreet = order.ReceiverStreet + " " + order.House;
                }
            }
            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 (channel.Id == 213 || channel.Id == 215)
            {
                if (order.CustomerWeight > 2200)
                {
                    order.CustomerWeight = 2200;
                }
            }
        }
        private void CreateOrderParamJude(CreateOrderParam param, Logistics_Channel channel)
        {
            if (channel.Id == 212)
            {
                param.JsonProductInfo.First().Sku = "JN-K-FC-1";
            }
            if (channel.Id == 213)
            {
                param.JsonProductInfo.First().Sku = "JN-K-PM-1";
            }
            if (channel.Id == 214)
            {
                param.JsonProductInfo.First().Sku = "JN-K-FC-2";
            }
            if (channel.Id == 215)
            {
                param.JsonProductInfo.First().Sku = "JN-K-PM-2";
            }

            if (channel.Id == 233)
            {
                param.JsonProductInfo.First().Sku = "JN-P-FC-1";
            }
            if (channel.Id == 234)
            {
                param.JsonProductInfo.First().Sku = "JN-P-PM-1";
            }
            if (channel.Id == 235)
            {
                param.JsonProductInfo.First().Sku = "JN-P-FC-2";
            }
            if (channel.Id == 236)
            {
                param.JsonProductInfo.First().Sku = "JN-P-PM-2";
            }
            if (channel.Id == 237)
            {
                param.JsonProductInfo.First().Sku = "JN-P-FC-3";
            }
            if (channel.Id == 238)
            {
                param.JsonProductInfo.First().Sku = "JN-P-PM-3";
            }


            if (channel.Id == 244)
            {
                param.JsonProductInfo.First().Sku = "JN-F-FC-1";
            }
            if (channel.Id == 245)
            {
                param.JsonProductInfo.First().Sku = "JN-F-PM-1";
            }
            if (channel.Id == 246)
            {
                param.JsonProductInfo.First().Sku = "JN-F-FC-2";
            }
            if (channel.Id == 247)
            {
                param.JsonProductInfo.First().Sku = "JN-F-PM-2";
            }
            if (channel.Id == 248)
            {
                param.JsonProductInfo.First().Sku = "JN-F-FC-3";
            }
            if (channel.Id == 250)
            {
                param.JsonProductInfo.First().Sku = "JN-F-PM-3";
            }

            if (channel.Id == 205)
            {
                param.JsonProductInfo.First().Sku = "JN-O";
            }
            if (channel.Id == 269)
            {
                param.JsonProductInfo.First().Sku = "JN-Y-FC-3";
            }
            if (channel.Id == 270)
            {
                param.JsonProductInfo.First().Sku = "JN-Y-PM-3";
            }
        }
        #endregion
        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)
        {
            var client = new RestClient($"{(!string.IsNullOrEmpty(model.ApiHost) ? model.ApiHost : "http://services.frayun.com/Service.asmx")}/Delete?UserName={model.ApiKey}&PassWord={model.ApiSecret}&DpdNo={model.SystemNo}");
            client.Timeout = -1;
            var request = new RestRequest(Method.GET);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            try
            {
                IRestResponse response = client.Execute(request);
                model.OriginalMessage = response.Content;
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(response.Content);
                string json = doc.InnerText;
                DeleteResponse deleteResponses = JsonConvert.DeserializeObject<List<DeleteResponse>>(json).FirstOrDefault();
                if (deleteResponses.ResultCode == "00000" || deleteResponses.ErrorMsg.Contains("包裹不存在")) { model.ResultState = ResultStateEnum.成功.GetValue(); } else { model.ResultState = ResultStateEnum.失败.GetValue(); }
                model.ResponseCode = deleteResponses.ResultCode;
                model.ResultMessage = deleteResponses.ErrorMsg;
            }
            catch (Exception ex)
            {
                model.ResultState = ResultStateEnum.异常.GetValue(); model.ResultMessage = ex.Message;
            }
        }

        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, channel);
            string userName = channel.ApiKey;
            string password = channel.ApiSecret;
            string senderType = channel.ServiceChannelCode.Split(';')[0];
            string serialNumber = channel.ServiceChannelCode.Split(';').Length > 1 ? channel.ServiceChannelCode.Split(';')[1] : null;
            int weight = channel.IsTransfer && order.OPWeight > 0 ? order.OPWeight : order.CustomerWeight;
            CreateOrderParam param = new CreateOrderParam
            {
                ActualWeight = (weight / 1000d).ToString("F3"),
                ClientNumber = order.SystemNo,
                IsCharged = 0,
                ReceiveAddress = order.ReceiverStreet,
                ReceiveCity = order.ReceiverCity,
                ReceiveCode = order.ReceiverZipCode,
                ReceiveComName = string.Empty,
                ReceiveCountry = order.ReceiverCountryCode,
                ReceiveEmail = order.ReceiverEmail,
                ReceiveName = order.ReceiverName,
                ReceiveProvince = order.ReceiverState,
                ReceiveTel = order.ReceiverPhone,
                SendType = senderType,
                JsonProductInfo = new List<ProductInfoItem>(),
                SerialNumber = serialNumber
            };
            if (goods != null)
            {
                int unitWeight = order.OPWeight / goods.Count == 0 ? 1 : goods.Count;
                goods.ForEach(i =>
                {
                    ProductInfoItem item = new ProductInfoItem
                    {
                        Packages = i.Quantity,
                        ProduceNameCN = i.CnName,
                        ProduceNameEN = i.EnName,
                        Sku = string.Empty,
                        USD = (double)(i.DeclareFee * i.Quantity),
                        Weight = i.Weight == 0 ? unitWeight : i.Weight * i.Quantity,
                    };
                    param.JsonProductInfo.Add(item);
                });
                CreateOrderParamJude(param, channel);
            }
            else throw new Exception("报关物品明细不能为空");
            string onlyId = order.SystemNo;
            string dpdNo = string.Empty;
            if (order.CustomerId == 301)
            {
                onlyId = order.CustomerOrderNo;
                dpdNo = _orderRepository.GetChannelOrderInfoRecord(channel.Id, onlyId).Result;
            }
            FrayunAPI.ServiceSoapClient client = new FrayunAPI.ServiceSoapClient(FrayunAPI.ServiceSoapClient.EndpointConfiguration.ServiceSoap);
            //代理设置
            var b = client.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
            FiddlerClient.SetProxy(b);
            List<CreateOrderResult> results = null;
            if (!string.IsNullOrEmpty(dpdNo))
            {
                results = new List<CreateOrderResult>
                {
                    new CreateOrderResult
                    {
                        DpdNo = dpdNo,
                        ResultCode = "00011"
                    }
                };
            }
            else
            {
                string jsonParam = Newtonsoft.Json.JsonConvert.SerializeObject(param);
                string restJson = client.CreatePreToJsonAsync(userName, password, jsonParam).Result;
                results = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CreateOrderResult>>(restJson);


            }


            if (results == null || results.Count == 0)
            {
                throw new Exception("下单结果集合为空");
            }
            var result = results[0];
            //if (channel.Id == 123 || channel.Id == 189 || channel.Id == 205 || channel.Id == 212 || channel.Id == 213)
            //{
            if (result.ResultCode == "00011")
            {
                //客单号已存在的，我们直接返回已有订单信息，不再报错
                var resultJson = client.GetPdfPreAsync(userName, password, !string.IsNullOrEmpty(result.DpdNo) ? result.DpdNo : order.SystemNo);
                var resultItems = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PdfResultItem>>(resultJson.Result);
                if (resultItems != null && resultItems.Count > 0)
                {
                    var pdfInfo = resultItems[0];
                    if (pdfInfo.ResultCode == "00000")
                    {
                        if (string.IsNullOrEmpty(pdfInfo.DpdNo))
                        {
                            throw new Exception("运单号返回为空");
                        }
                        return new UploadResult
                        {
                            destinationCode = order.ReceiverCountryCode,
                            DownloadUrl = string.Empty,
                            IsSuccess = true,
                            IsTransfer = false,
                            ServiceOrderNumber = result.DpdNo,
                            TrackingNumber = result.DpdNo,
                        };
                    }
                    else
                    {
                        throw new Exception("重新获取面单时报错:" + pdfInfo.ErrorMsg);
                    }
                }
                else
                {
                    throw new Exception("面单返回结果为空");
                };
            }
            if (string.IsNullOrEmpty(result.ErrorMsg))
            {
                if (string.IsNullOrEmpty(result.DpdNo))
                {
                    throw new Exception("运单号返回为空");
                }
                UploadResult uploadResult = new UploadResult
                {
                    destinationCode = order.ReceiverCountryCode,
                    DownloadUrl = string.Empty,
                    IsSuccess = true,
                    IsTransfer = false,
                    ServiceOrderNumber = result.DpdNo,
                    TrackingNumber = result.DpdNo,
                };

                _orderRepository.AddChannelOrderInfoRecord(result.DpdNo, onlyId, channel.Id);
                return uploadResult;
            }

            else throw new Exception($"{result.ErrorMsg}");
        }

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

            if (string.IsNullOrEmpty(result.TrackingNumber))
            {
                throw new Exception("跟踪号获取失败，请重试");
            }
            FrayunAPI.ServiceSoapClient client = new FrayunAPI.ServiceSoapClient(FrayunAPI.ServiceSoapClient.EndpointConfiguration.ServiceSoap);
            //代理设置
            var b = client.Endpoint.Binding as System.ServiceModel.BasicHttpBinding;
            FiddlerClient.SetProxy(b);

            string userName = channel.ApiKey;
            string password = channel.ApiSecret;
            string resultJson = client.GetPdfPreAsync(userName, password, result.TrackingNumber).Result;
            if (string.IsNullOrEmpty(resultJson))
                throw new Exception("获取面单返回结果为空");
            else
            {
                var resultItems = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PdfResultItem>>(resultJson);
                if (resultItems != null && resultItems.Count > 0)
                {
                    var item = resultItems[0];
                    if (channel.Id == 189 && !string.IsNullOrEmpty(item.ErrorMsg) && item.ErrorMsg.Contains("包裹未就绪"))
                    {
                        //暂停5S下载面单
                        System.Threading.Thread.Sleep(5000);
                    }
                    //string resultMsg = GetPdfResultMessage(item?.ResultCode); 
                    if (string.IsNullOrEmpty(item.ErrorMsg))
                    {
                        if (string.IsNullOrEmpty(item?.PdfUrl))
                            throw new Exception("面单地址为空");

                        WebClient wc = new WebClient();
                        byte[] data = null;
                        int i = 1;
                        for (; i <= 6; i++)
                        {
                            try
                            {
                                data = wc.DownloadData(item.PdfUrl);
                                if (data.Length > 5000)
                                    break;
                                else
                                    Thread.Sleep(1000);
                            }
                            catch
                            {
                                Thread.Sleep(1000);
                            }
                        }
                        if (data == null || data.Length == 0)
                            throw new Exception($"下载面单结果为空,已重试{i}次");
                        else
                        {
                            result.TrackingNumber = item.TurnNo;

                            if (string.IsNullOrEmpty(item.TurnNo))
                            {
                                throw new Exception("运单号返回为空");
                            }
                            if (channel.Id == 123)
                                data = PDFHelper.Watermark(data, order.SystemNo, 1, 90, 35, 13, iTextSharp.text.BaseColor.BLACK);

                            return data;
                        }
                    }
                    else
                        throw new Exception($"{item.ErrorMsg}");
                }
                else
                    throw new Exception("面单返回结果集合为空");
            }
        }

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