using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Common.Standard;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using System.Security.Cryptography;
using RestSharp;
using XYY.Core.Standard.PDF;

namespace XYY.Service.Standard.ChannelApi.HuanYang
{
    public class Api : IBaseApi
    {
        public string ServiceName => "HuanYang";

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

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

        public void CannelOrdersByModel(logistics_ChannelCancel logistics_ChannelCancel)
        {
            throw new NotImplementedException();
        }

        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)
        {
            RequestParam requestParam = CreateRequestParam(order, goods, channel);

            ResponseParam response = await SendRequest<ResponseParam>(requestParam, channel, "/platformOutsideInterfaces/apis/common/singlePushOrder/1.0", "inglePushOrder");

            CheckError(response);

            OrderPushResult result = CreateOrderPushResult(response.body);

            var uploadResult = new UploadResult
            {
                DownloadUrl = result.orderPrintPath,
                Error = null,
                IsSuccess = true,
                IsTransfer = false,
                ResponseContent = null,
                ServiceOrderNumber = result.waybillNo,
                ServiceOrderNumber2 = null,
                ServiceOrderNumber3 = null,
                ServierFee = 0,
                TrackingNumber = result.transNo,
                TransferNumner = order.TransferNumber,
            };
            return uploadResult;

        }

        private OrderPushResult CreateOrderPushResult(string body)
        {
            try
            {
                return Newtonsoft.Json.JsonConvert.DeserializeObject<OrderPushResult>(body);
            }
            catch (Exception ex)
            {
                throw new Exception("解析下单结果失败", ex);
            }

        }

        private async Task<T> SendRequest<T>(RequestParam requestParam, Logistics_Channel channel, string url, string command)
        {
            string requestId = Guid.NewGuid().ToString("n");
            string appId = channel.ApiKey;
            RestClient restClient = new RestClient(channel.ApiHost);
            RestRequest req = new RestRequest(url);

            string paramJson = Newtonsoft.Json.JsonConvert.SerializeObject(requestParam);
            string device_id = "tester";
            string isEncoded = "false";
            string version = "1.4";
            string encrypt_type = "0";
            string sign = CreateSign(appId, paramJson, command, device_id, encrypt_type, version, channel.ApiSecret);
            //string body = $"appid={appId}&command={command}&version=1.4&encrypt_type=0&device_id=tester&isEncoded=false&reqUuid={requestId}&sign={sign}&body={paramJson}";
            req.AddParameter("appid", appId);
            req.AddParameter("command", command);
            req.AddParameter("version", version);
            req.AddParameter("encrypt_type", encrypt_type);
            req.AddParameter("device_id", device_id);
            req.AddParameter("isEncoded", isEncoded);
            req.AddParameter("reqUuid", requestId);
            req.AddParameter("sign", sign);
            req.AddParameter("body", paramJson);

            req.AddHeader("Content-Type", "application/x-www-form-urlencoded");

            var resp = await restClient.ExecuteAsync(req, Method.POST);

            if (resp.IsSuccessful)
            {
                try
                {
                    string content = resp.Content.Replace("哲盟", "API");//过滤调渠道商字眼
                    T result = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(content);
                    return result;
                }
                catch (Exception ex)
                {
                    string msg = resp.Content;
                    var newEx = new Exception(msg, ex);
                    throw newEx;
                }
            }
            else
            {
                var msg = resp.ErrorMessage.Replace("哲盟", "API");//过滤调渠道商字眼;
                throw new Exception(msg);
            }

        }

        private RequestParam CreateRequestParam(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel)
        {
            decimal weightKg = (order.OPWeight <= 0 ? order.CustomerWeight : order.OPWeight) / 1000m;


            RequestParam param = new RequestParam();
            param.waybillNo = "";
            param.transNo = "";
            param.destNo = order.ReceiverCountryCode;
            param.refNo = order.TransferNumber;
            param.transType = channel.ServiceChannelName;//渠道说用示例里面的也可以
            param.packageType = "WPX";
            param.pcs = 1;
            param.weight = weightKg;
            param.goodsType = "普货";

            param.payType = "PP";
            //param.payment = "";

            param.remark = "";
            param.senderName = "Benny";
            param.senderCompanyName = "XYY";
            param.senderPostcode = "510000";
            param.senderCountry = "CN";
            param.senderProvince = "GUANGDONG";
            param.senderCity = "GUANGZHOU";
            param.senderAddr = "303, Building B, Huijin Plaza, No. 770, North Baiyun Avenue, Baiyun District";

            param.receiverName = order.ReceiverName;
            param.receiverCompanyName = order.ReceiverCompany;
            param.receiverTel = order.ReceiverPhone;
            param.receiverPostcode = order.ReceiverZipCode;
            param.receiverEmail = order.ReceiverEmail;
            param.receiverAddr = order.ReceiverStreet;
            param.receiverCity = order.ReceiverCity;
            param.receiverProvince = order.ReceiverState;
            param.receiverCountry = order.ReceiverCountryCode;
            param.declareType = 1;
            param.receiverCompanyName = String.IsNullOrWhiteSpace(order.ReceiverCompany)?order.ReceiverName: order.ReceiverCompany;
            param.universalCompile = "";

            List<Customs> orderGoods = CreateOrderGoods(order, goods);
            param.customs = orderGoods;
            List<OrderSingInfoVOs> sigleInfo = CreateOrderSingleInfo(weightKg);
            param.orderSingInfoVOs = sigleInfo;

            return param;
        }

        private List<OrderSingInfoVOs> CreateOrderSingleInfo(decimal weight)
        {
            OrderSingInfoVOs vos = new OrderSingInfoVOs
            {
                height = 1,
                length = 1,
                width = 1,
                vol = 1,
                weight = weight
            };
            return new List<OrderSingInfoVOs> { vos };
        }

        private List<Customs> CreateOrderGoods(Order_Order order, List<Order_OrderGoods> goods)
        {
            List<Customs> result = new List<Customs>();
            foreach (var g in goods)
            {
                Customs c = new Customs
                {
                    cargoNameCn = g.CnName,
                    cargoNameEn = g.EnName,
                    currency = "USD",
                    declareQty = g.Quantity,
                    unitPrice = g.DeclareFee
                };
                result.Add(c);
            }
            return result;
        }

        private void CheckError(ResponseParam response)
        {
            if (response == null)
            {
                throw new Exception("响应数据为空");
            }
            else if (response.result_code != 0)
            {
                string msg = $"错误代码:{response.result_code}+{response.message ?? "API错误"}{response.body ?? ""}";
                throw new Exception(msg);
            }
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            var bytes = await Task.Run(() =>
            {
                try
                {
                    string base64 = result.DownloadUrl;
                    byte[] data = null;

                    if (result.DownloadUrl.StartsWith("http"))
                    {
                        data = new System.Net.WebClient().DownloadData(result.DownloadUrl);
                        if (data.Length < 1000)
                            throw new Exception("面单获取失败");
                    }
                    else
                    {

                        data = Convert.FromBase64String(base64);
                    }
                    return data;
                }
                catch (Exception ex)
                {
                    throw new Exception("解析面单base64数据失败", ex);
                }
            });
            return bytes;
        }

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

        private string CreateSign(string appid, string body, string command, string device_id, string encrypt_type, string version, string appSecret)
        {
            string raw = $"{appid}{body}{command}{device_id}{encrypt_type}{version}{appSecret}";
            string sign = GetMd5Str(raw);
            return sign;
        }


        string GetMd5Str(string ConvertString)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(ConvertString)), 4, 8);
            t2 = t2.Replace("-", "");

            t2 = t2.ToLower();

            return t2;
        }
    }
}
