using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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;

namespace XYY.Service.Standard.ChannelApi.JD
{
    public partial class Api : IBaseApi
    {
        private const string customerCode = "KH20000001419";
        private const string app_key = "ef729d8a2f184af7a81fce1a5fd9dc82";
        //access_token获取方式请参考《【商家版】-FOP跨境开发者文档-中文版v2.3.doc》手册第6章
        private const string access_token = "0cc8b088faa34eca8743fa5c0df153ba";
        private const string app_secret = "17d26ade49404d1497f0a2a3a1b193f9";
        private const string pin = "jdhk_bBGtofutWiKH";
        private const string @operator = "admin";
        private const string sourceSystem = "LMJ";
        private const string host = "https://us-api.jd.com/routerjson";



        public string ServiceName => "JD-USLINE-2";

        IOrderRepository _orderRepository;
        public Api(IOrderRepository orderRepository)
        {
            _orderRepository = orderRepository;
        }

        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)
        {
            string sellerId = "";
            string storeId = "";
            string orderNumber = order.TransferNumber.Replace("XYY", "LMJ");//不要出现XYY字眼
            var wayBillDto = CreateWayBillDto(customerCode, sellerId, storeId, order, goods, channel, orderNumber);
            RequestInfo requestInfo = CreateRequestInfo();

            //string wayBillJson = Newtonsoft.Json.JsonConvert.SerializeObject(wayBillDto);
            //string requestInfoJson = Newtonsoft.Json.JsonConvert.SerializeObject(requestInfo);
            //string paramJson = $"[{requestInfoJson},{wayBillJson}]";

            RestRequest request = CreateRestRequst(requestInfo, wayBillDto, out string paramJson);
            string method = "jingdong.fop.service.deliveryWaybill";

            RestClient client = createRestClient(method, paramJson);
            //RestClient client = new RestClient(url);
            //RestRequest request = new RestRequest();
            //request.Method = Method.POST;
            //request.AddParameter("application/json;charset=UTF-8", paramJson, ParameterType.RequestBody);


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

                WayBillResult responseResult = result.Data;
                if (responseResult?.response == null)
                {
                    responseResult = Newtonsoft.Json.JsonConvert.DeserializeObject<WayBillResult>(content);
                }
                if (responseResult?.response == null)
                {
                    throw new Exception($"渠道返回响应为空或格式不正确:{content}");
                }
                var response = responseResult.response;
                if (response.code == 0)
                {
                    var serviceOrderNumber = response.content.data;
                    if (!string.IsNullOrWhiteSpace(serviceOrderNumber))
                    {
                        await _orderRepository.AddChannelOrderInfoRecord(channel.Id, serviceOrderNumber, orderNumber);
                        var uploadResult = await RequestLabel(serviceOrderNumber, orderNumber);
                        return uploadResult;
                    }
                    else
                    {
                        if (!response.content.success)
                        {
                            string msg = response.content.errorMsg;
                            if (string.IsNullOrWhiteSpace(msg))
                                msg = content;
                            //单号重复
                            if (msg.Contains($"Issue:Parameter validation failed: {orderNumber}"))
                            {
                                UploadResult uploadResult2 = await RetryRequestLabel(channel.Id, orderNumber);
                                return uploadResult2;
                            }
                            else
                            {
                                throw new Exception($"下单api返回错误:{msg}");
                            }


                        }
                        else
                            throw new Exception("下单api返回订单数据为空");
                    }
                }
                else
                {
                    string msg = content;
                    string msg2 = response.content?.errorMsg;
                    throw new Exception($"下单出错： {msg} {msg2},错误代码:{response.code}");
                }
            }
            else
            {
                string msg = string.IsNullOrWhiteSpace(result.ErrorMessage) ? result.Content : result.ErrorMessage;
                throw new Exception(msg);
            }

        }

        private async Task<UploadResult> RetryRequestLabel(int channelId, string orderNumber)
        {
            string serviceNumber = await _orderRepository.GetChannelOrderInfoRecord(channelId, orderNumber);
            if (string.IsNullOrEmpty(serviceNumber))
                throw new Exception("渠道API提示单号重复，但找不到记录的服务单号");
            var result = await RequestLabel(serviceNumber, orderNumber);
            return result;
        }

        private RestClient createRestClient(string method, string paramJson)
        {
            //string method = "jingdong.fop.service.deliveryWaybill";
            string timeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            string sign = SignHelper.CreateSign(paramJson, app_secret, access_token, app_key, method, timeStamp);

            string query = CreateRequestQuery(method, access_token, app_key, sign, timeStamp);
            string url = $"{host}?{query}";

            RestClient client = new RestClient(url);
            return client;
        }

        private RestRequest CreateRestRequst(RequestInfo requestInfo, object param, out string paramJson)
        {
            RestRequest request = new RestRequest();
            string wayBillJson = Newtonsoft.Json.JsonConvert.SerializeObject(param);
            string requestInfoJson = Newtonsoft.Json.JsonConvert.SerializeObject(requestInfo);
            paramJson = $"[{requestInfoJson},{wayBillJson}]";
            request.Method = Method.POST;
            request.AddParameter("application/json;charset=UTF-8", paramJson, ParameterType.RequestBody);
            return request;
        }

        private async Task<UploadResult> RequestLabel(string serviceOrderNumber, string orderNumber)
        {
            var printDto = CreateWaybillPrintDTO(customerCode, pin, orderNumber);
            RequestInfo requestInfo = CreateRequestInfo();
            RestRequest request = CreateRestRequst(requestInfo, printDto, out string paramJson);
            string method = "jingdong.fop.waybill.printWaybill";
            RestClient client = createRestClient(method, paramJson);

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

                WayBillPrintResult responseResult = result.Data;
                if (responseResult == null)
                {
                    responseResult = Newtonsoft.Json.JsonConvert.DeserializeObject<WayBillPrintResult>(content);
                }
                if (responseResult?.response == null || responseResult.response == null)
                {
                    throw new Exception("打印面单:渠道返回响应为空或格式不正确");
                }
                var response = responseResult.response;
                if (response.code == 0)
                {
                    var dict = response.content.data?.packageSheetInfoMap;
                    if (dict != null && dict.ContainsKey(orderNumber))
                    {
                        var val = dict[orderNumber];
                        UploadResult uploadResult = new UploadResult
                        {
                            ServiceOrderNumber = serviceOrderNumber,
                            TrackingNumber = val.trackingNo,
                            DownloadUrl = val.billUrl,
                            IsSuccess = true
                        };
                        return uploadResult;
                    }
                    else
                    {
                        throw new Exception($"渠道api返回面单数据有误:{content}");
                    }
                }
                else
                {
                    string msg = content;
                    string msg2 = response.content?.errorMsg;
                    throw new Exception($"下载面单出错： {msg} {msg2},错误代码:{response.code}");
                }
            }
            else
            {
                string msg = string.IsNullOrWhiteSpace(result.ErrorMessage) ? result.Content : result.ErrorMessage;
                throw new Exception(msg);
            }

        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            byte[] data = await Task.Run<byte[]>(() =>
            {
                byte[] bytes = null;
                int maxCount = 3;
                RestClient client = new RestClient(result.DownloadUrl);
                RestRequest rq = new RestRequest(Method.GET);
                for (int i = 0; i < maxCount; i++)
                {
                    bytes = client.DownloadData(rq);
                    if (bytes == null || bytes.Length < 1500)
                    {
                        Thread.Sleep(1000);
                    }
                    else
                    {
                        if (channel.Id == 324)
                        {
                            bytes = PDFHelper.Watermark(bytes, "█", 1, -5, 420, 140, iTextSharp.text.BaseColor.WHITE);
                            //炜霖的面单需要打印sku信息
                            if (order.CustomerId == 250 || order.CustomerId == 227)
                            {
                                string sku = orderGoods.FirstOrDefault()?.GoodsNumber;

                                if (!string.IsNullOrWhiteSpace(sku))
                                {
                                    if (sku.Length > 40)
                                        sku = sku.Substring(0, 40);
                                    bytes = PDFHelper.Watermark(bytes, sku, 1, 10, 416, 8, iTextSharp.text.BaseColor.BLACK);
                                }

                            }
                        }
                        else if (channel.Id == 313)
                        {
                            bytes = PDFHelper.Watermark(bytes, "J", 1, 20, 16, 20, iTextSharp.text.BaseColor.BLACK);
                        }
                        return bytes;
                    }
                }
                throw new Exception("下载面单失败，数据长度不足");
            });
            return data;
        }

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

        private string CreateRequestQuery(string method, string access_token, string app_key, string sign, string timeStamp, string v = "2.0")
        {
            string temp = @$"sign={sign}&timestamp={timeStamp}&v={v}&app_key={app_key}&method={method}&access_token={access_token}";
            return temp;
        }
    }
}
