using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using XYY.Core.Standard.ExtendMethods;
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.MIQ
{
    public class Api : IBaseApi
    {
        public string ServiceName => "SK-ACI";
        private string testKey = "c24855-04bc7a-b44643-cb4d94-30b156";
        private string testHost = "http://rps.sandbox.miqexpress.com/";


        private async Task<List<BagDeclareErrosResult>> Submit(Logistics_Channel channel, string ladingBillNumber, IEnumerable<BoxDetailItem> boxDetailItems)
        {
            List<BagDeclareErrosResult> failedList = new List<BagDeclareErrosResult>();

            var items = boxDetailItems.Select(i => new ParcelItem { trackingNumber = i.TrackingNumber,sackId=i.BoxNumber,receptacleId=i.BoxNumber }).ToList();
            PushManifestParam param = new PushManifestParam
            {
                customerReference1 = ladingBillNumber,
                description = "XYY shipment",
                parcelList = items
            };

            string apiKey = CreateApiKey(channel);
            string host = channel.ApiHost;


            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/rps-api/manifest/submit");
            request.Method = Method.POST;
            request.AddJsonBody(param);
            request.AddHeader("api-key", apiKey);

            var response = await client.ExecuteAsync<SubmitManifestReponse>(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var content = response.Content;
                if (string.IsNullOrWhiteSpace(content))
                {
                    throw new Exception("推送Manifest返回数据为空");
                }

                SubmitManifestReponse data = response.Data;

                if (data.success == true)
                {
                    if (data.payload?.failList?.Any() == true)
                    {
                        var failList = data.payload.failList
                            .Where(i => i.errorMessage != "Already submitted" && i.errorMessage != "GEG: Label already submitted.")
                            .Select(i =>
                               new BagDeclareErrosResult { TrackingNumber = i.trackingNumber, ErrorMessage = i.errorMessage });
                        failedList.AddRange(failList);
                    }
                }
                else
                {
                    failedList =
                        boxDetailItems.Select(x => new BagDeclareErrosResult { ErrorMessage = data.message, TrackingNumber = x.TrackingNumber }).ToList();
                }
            }
            else
            {
                failedList =
                    boxDetailItems.Select(x =>
                        new BagDeclareErrosResult { ErrorMessage = response.Content ?? response.ErrorMessage, TrackingNumber = x.TrackingNumber }).ToList();
            }

            return failedList;

        }

        public async Task<List<BagDeclareErrosResult>> BagDeclare(BagDeclareRequest bagDeclareRequest)
        {

            int pageSize = 30000;
            List<BagDeclareErrosResult> failedResult = new List<BagDeclareErrosResult>();
            var channel = bagDeclareRequest.Channel;

            var allItems = bagDeclareRequest.BatchDeclare.Values.SelectMany(i => i);
            var ladingBillGroups = allItems.GroupBy(i => i.LadingBillNumber);
            foreach (var g in ladingBillGroups)
            {
                string ladingBillNumber = g.Key;
                var boxDetailItems = g.ToList();

                int totalCount = boxDetailItems.Count();
                int pageCount = (int)Math.Ceiling(totalCount / (double)pageSize);
                for (int p = 0; p < pageCount; p++)
                {
                    var pageItems = boxDetailItems.Skip(pageSize * p).Take(pageSize);

                    var failedList = await Submit(channel, ladingBillNumber, pageItems);
                    if (failedList?.Any() == true)
                    {
                        failedResult.AddRange(failedList);
                    }
                }

            }
            return failedResult;
        }

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

        public void CannelOrdersByModel(logistics_ChannelCancel channel)
        {
            string apiKey = channel.ApiKey;
            string host = channel.ApiHost;
            string trackingNumber = channel.TrackingNumber;

            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/rps-api/label/void-label");
            request.Method = Method.POST;

            request.AddParameter("trackingNumber", trackingNumber);
            request.AddHeader("api-key", apiKey);

            var response = client.Execute<VoidLableReponse>(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                if (!response.Data.success || response.Data.code != 200)
                {
                    string code = response.Data.code.ToString();
                    string errMsg = response.Data.message;
                    throw new Exception($"取消订单时出错:Code:{code},{errMsg}");
                }
            }
            else
            {
                string msg = response.Content;
                throw new Exception($"取消订单失败:{msg}");
            }
        }

        public async Task<List<string>> Confims(List<OrderConfimRequest> order, Logistics_Channel channel)
        {
            //批量确认订单信息

            string apiKey = channel.ApiKey;
            string host = channel.ApiHost;

            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/rps-api/label/void-label");
            request.Method = Method.POST;
            var trackingNumbers = order.Select(x => new { trackingNumber = x.TrackingNumber }).ToList();
            request.AddJsonBody(new
            {
                description = "shipment to LAX",
                parcelList = trackingNumbers
            });
            request.AddHeader("api-key", apiKey);


            var response = client.Execute<VoidLableReponse>(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                if (!response.Data.success || response.Data.code != 200)
                {
                    string code = response.Data.code.ToString();
                    string errMsg = response.Data.message;
                    throw new Exception($"推送manifest时出错:Code:{code},{errMsg}");
                }
            }
            else
            {
                string msg = response.Content ?? response.ErrorMessage;
                throw new Exception($"推送manifest时失败:{msg}");
            }

            return new List<string>();
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            string apiKey = CreateApiKey(channel);
            string host = channel.ApiHost;


            new USAddressCheck().CheckUSOrder(order, false);


            var port = ACIZipZones.GetPort(order.ReceiverZipCode);

            if (order.CustomerId != 294 && port != "LAX")
            {
                //throw new Exception("当前渠道目前只允许LAX的邮编");
            }

            //电话处理、电话大于20位时，我们做一个字符替换处理
            if (!string.IsNullOrEmpty(order.ReceiverPhone) && order.ReceiverPhone.Length > 20)
            {
                order.ReceiverPhone = order.ReceiverPhone.Replace("+", "").Replace("-", "").Replace(" ", "");
            }

            CheckRecepient(order);
            CreateOrderParam createOrderParam = GenCreateOrderParam(order, goods, channel, port);
            //var json = Newtonsoft.Json.JsonConvert.SerializeObject(createOrderParam);
            RestClient client = new RestClient(host);
            RestRequest request = new RestRequest("/rps-api/label/create-label");
            request.Method = Method.POST;

            request.AddJsonBody(createOrderParam);
            request.AddHeader("api-key", apiKey);

            var response = await client.ExecuteAsync<CreateLabelReponse>(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var content = response.Content;
                if (string.IsNullOrWhiteSpace(content))
                {
                    throw new Exception("下单api返回内容为空");
                }

                CreateLabelReponse data = response.Data;

                if (data.success == true)
                {
                    if (data.payload != null)
                    {
                        var result = data.payload;
                        string trackingNumber = result.trackingNumberShort;
                        string serviceOrderId = result.trackingNumber;
                        string labelBase64 = result.labelBase64;

                        byte[] labelData = null;
                        if (!string.IsNullOrWhiteSpace(labelBase64))
                        {
                            labelData = Convert.FromBase64String(labelBase64);
                        }
                        if (string.IsNullOrWhiteSpace(trackingNumber))
                        {
                            string msg = $"下单API返回错误:获取的跟踪号为空";
                        }



                        var uploadResult = new UploadResult
                        {
                            IsSuccess = true,
                            ServiceOrderNumber = serviceOrderId,
                            TrackingNumber = trackingNumber,
                            LabelData = labelData
                        };
                        return uploadResult;

                    }
                    else
                    {
                        throw new Exception("下单api返回订单数据为空");
                    }

                }
                else
                {
                    string msg = content;
                    throw new Exception($"下单出错 {msg}");
                }

            }
            else
            {
                string msg = string.IsNullOrWhiteSpace(response.ErrorMessage) ? response.Content : response.ErrorMessage;
                throw new Exception($"下单出错 {msg}");
            }
        }

        private string CreateApiKey(Logistics_Channel channel)
        {
            return channel.ApiSecret;
        }

        private CreateOrderParam GenCreateOrderParam(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, string port)
        {

            string courierCode = channel.ServiceChannelCode;
            //courierCode = "USPSFC";
            CustomizedInfoForm customizedInfoForm = GetCustomizedInfoForm(order);
            LabelSettingForm labelSettingForm = GetLabelSettingForm();
            Recipient recipient = GetRecipient(order);
            ReturnAddress returnAddress = GetReturnAddress();

            var orderWeight = order.OPWeight <= 0 ? order.CustomerWeight : order.OPWeight;

            CreateOrderParam param = new CreateOrderParam
            {
                carrierLeaveIfNoResponse = true,
                courierCode = courierCode,
                customizedInfoForm = customizedInfoForm,
                labelSettingForm = labelSettingForm,
                returnAddress = returnAddress,
                recipient = recipient,
                dimensionUom = "CM",
                height = 1,
                length = 1,
                machinable = false,
                portOfEntry = port,
                signature = false,
                validateAddress = true,
                weight = orderWeight,
                weightUom = "G",
                width = 1,
            };

            return param;
        }

        private ReturnAddress GetReturnAddress()
        {
            return null;
        }

        private void CheckRecepient(Order_Order order)
        {

            if (string.IsNullOrWhiteSpace(order.ReceiverStreet))
                throw new Exception($"收件人街道不能为空");
            if (!order.ReceiverStreet.IsASCII())
                throw new Exception($"收件人街道包含非ASCII的特殊字符");
            if (string.IsNullOrEmpty(order.ReceiverCity))
                throw new Exception($"收件人城市不能为空");
            if (!order.ReceiverCity.IsASCII())
                throw new Exception($"收件人城市包含非ASCII的特殊字符");
            if (string.IsNullOrWhiteSpace(order.ReceiverCountryCode)
                || !order.ReceiverCountryCode.IsASCII()
                || order.ReceiverCountryCode.Length > 2
                )
            {
                throw new Exception($"收件人国家代码必须为二字简码");
            }
            if (!string.IsNullOrEmpty(order.ReceiverEmail) && order.ReceiverEmail.Length > 255)
                throw new Exception($"收件人邮箱不能超过255个字符");
            if (string.IsNullOrWhiteSpace(order.ReceiverName))
                throw new Exception($"收件人姓名不能为空");
            if (!Regex.IsMatch(order.ReceiverName, @"^[a-z0-9A-Z\ \-\.]{1,35}$"))
                throw new Exception($"收件人姓名只能是字母或数字并且不能超过35个字符");
            if (!string.IsNullOrWhiteSpace(order.ReceiverPhone) && order.ReceiverPhone.Length > 35)
                throw new Exception($"收件人电话不能超过35个字符");

            if (string.IsNullOrWhiteSpace(order.ReceiverState))
                throw new Exception($"收件人省州不能为空");
            if (order.ReceiverCountryCode == "US" && order.ReceiverState.Length != 2)
                throw new Exception($"收件人省州必须为二字代码");

            if (string.IsNullOrWhiteSpace(order.ReceiverZipCode))
                throw new Exception($"收件人邮编不能为空");
            //if (order.ReceiverZipCode.Length != 5)
            //    throw new Exception($"收件人邮编长度必须为5");
        }

        private Recipient GetRecipient(Order_Order order)
        {
            string[] addresses = order.ReceiverStreet.ToArray(35);
            if (addresses.Length > 2)
                throw new Exception("地址超长");
            string street1 = addresses[0];//max len 80,ascii only
            string street2 = addresses.Length > 1 ? addresses[1] : null;
            string city = order.ReceiverCity;
            string countryCode = order.ReceiverCountryCode;
            string email = order.ReceiverEmail;

            string receiverName = order.ReceiverName;
            string companyName = order.ReceiverCompany;
            string phoneNumber = order.ReceiverPhone;
            string state = order.ReceiverState;
            string zipCode = order.ReceiverZipCode;
            Recipient recipient = new Recipient
            {
                recipientAddress1 = street1,
                recipientAddress2 = street2,
                recipientCity = city,
                recipientCountry = countryCode,
                recipientEmail = email,
                recipientName = receiverName,
                recipientOrgName = companyName,
                recipientPhone = phoneNumber,
                recipientState = state,
                recipientZip4 = null,
                recipientZip5 = zipCode
            };
            if (order.ReceiverZipCode.Length > 5)
            {
                recipient.recipientZip5 = order.ReceiverZipCode.Substring(0, 5);
            }
            if (order.ReceiverZipCode.Contains('-'))
            {
                order.ReceiverZipCode.Split('-');
                string zip4 = order.ReceiverZipCode.Split('-')[1];
                if (zip4.Length == 4)
                {
                    recipient.recipientZip4 = zip4;
                }
            }
            if (string.IsNullOrWhiteSpace(recipient.recipientZip4) && order.ReceiverZipCode.Length == 9)
            {
                //订单9位邮编无-号时，我们再拆一次
                recipient.recipientZip4 = order.ReceiverZipCode.Substring(5, 4);
            }
            return recipient;
        }

        private CustomizedInfoForm GetCustomizedInfoForm(Order_Order order)
        {
            return new CustomizedInfoForm
            {
                customizedInfoType = "BARCODE",
                customizedBarcodeValue = order.SystemNo
            };
        }

        private LabelSettingForm GetLabelSettingForm()
        {
            LabelSettingForm form = new LabelSettingForm
            {
                labelFormat = "PDF",
                returnBase64 = false,
                showLogo = false
            };
            return form;
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            byte[] data = result.LabelData;
            if (data != null)
            {
                return data;
            }
            else
            {
                string trackingNumber = result.TrackingNumber;
                RestClient restClient = new RestSharp.RestClient(channel.ApiHost);
                string url = $"/rps-api/label/get-label-base64/pdf/{trackingNumber}";
                RestRequest req = new RestRequest(url, Method.GET);
                string apiKey = CreateApiKey(channel);
                req.AddHeader("api-key", apiKey);
                var response = await restClient.ExecuteAsync<GetLabelResponse>(req);

                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    GetLabelResponse labelResponse = response.Data;
                    if (labelResponse == null)
                    {
                        string msg = "获取面单API返回响应无效";
                        throw new Exception(msg);
                    }
                    if (labelResponse.success)
                    {
                        if (labelResponse.payload == null)
                        {
                            throw new Exception("获取面单API返回标签数据为空");
                        }
                        var label = labelResponse.payload.labelBase64;
                        if (string.IsNullOrWhiteSpace(label))
                        {
                            throw new Exception("获取面单API返回标签内容为空");
                        }

                        try
                        {
                            var bytes = Convert.FromBase64String(label);
                            return bytes;
                        }
                        catch (Exception ex)
                        {
                            throw new Exception($"解析标签数据失败:{ex.Message}");

                        }

                    }
                    else
                    {
                        throw new Exception($"面单下载失败:{labelResponse.message}");
                    }
                }
                else
                {
                    throw new Exception("面单下载失败 " + response.ErrorMessage ?? response.Content);
                }
            }
        }

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