using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using XYY.Data.Standard.Order;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Core.Standard.ExtendMethods;

namespace XYY.Service.Standard.ChannelApi.QuadProTMS
{
    public partial class Api : IBaseApi
    {
        public Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        ILogger<Api> _logger;

        private IOrderRepository _orderRepository { get; set; }
        public Api(ILogger<Api> logger, IOrderRepository orderRepository)
        {
            _logger = logger;
            _orderRepository = orderRepository;
        }

        public string ServiceName => "QuadProTMS";

        public static string MD5Encrypt(string strSource)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] data = Encoding.UTF8.GetBytes(strSource);
            byte[] md5data = md5.ComputeHash(data);
            md5.Clear();
            string str = "";
            for (int i = 0; i < md5data.Length; i++)
            {
                str += md5data[i].ToString("x").PadLeft(2, '0');
            }
            return str;
        }

        public string GetToken(Logistics_Channel channel)
        {
            var clientKey = channel.ApiKey;
            var clientSecret = channel.ApiSecret;
            var ver = "1.0";
            string soure = $"{clientKey}{clientSecret}{ver}";
            string md5 = MD5Encrypt(soure);
            return md5;
        }

        public async Task<T> Send<T>(Logistics_Channel channel, string host, object obj)
        {
            RestSharp.RestClient client = new RestSharp.RestClient(host);
            //client.Proxy = new WebProxy("127.0.0.1:8888");

            RestSharp.RestRequest request = new RestSharp.RestRequest();
            string token = GetToken(channel);
            request.AddHeader("key", channel.ApiKey);
            request.AddHeader("token", token);
            request.AddHeader("version", "1.0");
            RestSharp.IRestResponse response = null;
            if (obj != null)
            {
                request.AddJsonBody(obj);
                response = await client.ExecutePostAsync(request);
            }
            else
            {
                response = await client.ExecuteGetAsync(request);
            }

            ;
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {

            }
            else
            {
                throw new Exception("下家服务错误" + (response.ErrorMessage ?? response.Content));
            }
            var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Result<T>>(response.Content);
            if (result.responseCode == 0)
            {
                return result.result;
            }
            else
            {
                throw new Exception(result.errorMessage + ":" + token);
            }

        }

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

        public Task<List<string>> Confims(List<OrderConfimRequest> order, Logistics_Channel channel)
        {
            throw new NotImplementedException();
        }
        //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 Api(OrderRepository orderRepository)
        {
            _orderRepository = orderRepository;
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            var channelOrderId = await _orderRepository.GetChannelOrderInfoRecord(channel.Id, order.SystemNo);
            if (string.IsNullOrEmpty(channelOrderId))
            {
                var result = await CreateOrerAsApi(order, goods, channel);
                await _orderRepository.AddChannelOrderInfoRecord(channel.Id, result.ServiceOrderNumber, order.SystemNo);
                return result;
            }
            else
            {
                var response = await Send<CreareOrderResult>(channel, channel.LabelUrl.Formater(channelOrderId), null);
                if (response.errorCode != 0)
                    throw new Exception(response.errorMessage);
                return ConvertResult(response);
            }

        }

        private async Task<UploadResult> CreateOrerAsApi(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            string enName = string.Join(',', goods.GroupBy(x => x.EnName).Select(x => x.Key).Distinct().ToArray());
            string cnName = string.Join(',', goods.GroupBy(x => x.CnName).Select(x => x.Key).Distinct().ToArray());
            OrderRequeust orderRequeust = new OrderRequeust
            {
                articleEnglishName = enName,
                articleName = cnName,
                customerRefNo = order.SystemNo,
                generateLabel = true,
                generateLabelUrl = true,
                imageType = "pdf",
                nonDeliveryOption = "RETURN",
                provider = channel.ServiceChannelCode,
                totalDeclaredValue = goods.Sum(x => x.Quantity * x.DeclareFee).ToString("0.000"),
                totalDeclaredValueCurrency = "美元",
                waybillType = "2",
                weight = order.CustomerWeight / 1000.0,
                weightUnit = "千克",
                items = new List<ItemsItem>(),
            };
            var array = order.ReceiverStreet.ToArray(50);
            if (array.Length > 2)
                throw new Exception("地址超长");
            string zip5 = "";
            string zip4 = "";
            if (order.ReceiverZipCode.Contains("-"))
            {
                zip5 = order.ReceiverZipCode.Split('-')[0];
                zip4 = order.ReceiverZipCode.Split('-')[1];
            }
            else
            {
                zip5 = order.ReceiverZipCode.Substring(0, 5);
            }
            orderRequeust.ToAddress = new ToAddress
            {
                address1 = array.Length == 2 ? array[1] : string.Empty,
                address2 = array[0],
                city = order.ReceiverCity,
                countryCode = order.ReceiverCountryCode,
                zipCode5 = zip5,
                zipCode4 = zip4,
                phone = order.ReceiverPhone,
                name = order.ReceiverName,
                state = order.ReceiverState,
                firm = order.ReceiverName
            };
            orderRequeust.items = goods.Select(x => new ItemsItem
            {
                cargoEnglishName = x.EnName,
                cargoName = x.CnName,
                declaredValue = (x.DeclareFee * x.Quantity).ToString("0.000"),
                declaredValueCurrency = "美元",
                hscode = x.HsCode,
                unitPrice = x.DeclareFee.ToString("0.000"),
                qty = x.Quantity
            }).ToList();

            var response = await Send<CreareOrderResult>(channel, channel.ApiHost, orderRequeust);
            if (response.errorCode != 0)
                throw new Exception(response.errorMessage);
            return ConvertResult(response);
        }

        private static UploadResult ConvertResult(CreareOrderResult response)
        {
            return new UploadResult
            {
                DownloadUrl = response.fileUrl,
                TrackingNumber = response.barCode,
                ServiceOrderNumber = response.waybillNo,
                IsSuccess = true
            };
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            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 void CannelOrders(List<string> systemNO)
        {
            throw new NotImplementedException();
        }
        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }
    }
}
