using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.ExtendMethods;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using RestSharp;
using Elasticsearch.Net;
using NPOI.SS.Formula.Functions;
using System.Threading;
using XYY.Data.Standard.Order;
using System.IO;

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

        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 token = GetToken(channel);
            CreateOrderParam createOrderParam = GetCreateOrderParam(token, channel, order, goods);

            CreateOrderResponse resp = await InvokeApi<CreateOrderResponse>("/api/open/customer/order", channel, createOrderParam);

            if (resp != null && resp.data?.Any() == true)
            {
                if ((resp.error || resp.code != "2000") && !IsOrderDuplicate(resp.message))
                {
                    string msg = resp.message;
                    msg += MapCodeError(resp.code);
                    if (resp.data?.Any() == true)
                    {
                        string innerMsg = string.Join(",", resp.data.Where(d => string.Equals(d.hasError, "yes")).Select(d => d.tips));
                        if (!string.IsNullOrEmpty(innerMsg))
                        {
                            msg += innerMsg;
                        }
                    }
                    throw new Exception($"错误:API返回错误:{msg}");
                }
                else
                {
                    var orderItem = resp.data.First();
                    if (string.Equals(orderItem.hasError, "yes"))
                    {
                        throw new Exception($"错误:API返回错误:{orderItem.tips} {orderItem.orderId}");
                    }
                    else
                    {
                        return new UploadResult
                        {
                            IsTransfer = true,
                            TrackingNumber = order.TransferNumber,
                            IsSuccess = true,
                            ServiceOrderNumber = orderItem.orderToken,
                        };
                    }
                }
            }
            else
            {
                throw new Exception("错误:API返回数据为空");
            }
        }

        private bool IsOrderDuplicate(string message)
        {
            return !string.IsNullOrWhiteSpace(message) && message.Contains("order duplicated or existed", StringComparison.OrdinalIgnoreCase);
        }

        //private async Task<CreateOrderResponse> CreateOrder(Logistics_Channel channel, CreateOrderParam createOrderParam)
        //{
        //    RestClient client = new RestClient(channel.ApiHost);
        //    RestRequest request = new RestRequest("/api/open/customer/order", Method.POST);
        //    request.AddJsonBody(createOrderParam);
        //    var resp = await client.ExecuteAsync<CreateOrderResponse>(request);
        //    CheckHttpResponseError(resp);
        //    return resp.Data;
        //}

        private void CheckHttpResponseError<T>(IRestResponse<T> resp)
        {
            if (!resp.IsSuccessful)
            {
                string msg = resp.ErrorMessage ?? resp.Content ?? "请求API错误";
                throw new Exception($"错误:{msg}");
            }
        }

        private string GetToken(Logistics_Channel channel)
        {
            return channel.ApiKey;
        }

        private CreateOrderParam GetCreateOrderParam(string token, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> goods)
        {
            string productCode = channel.ServiceChannelCode;
            CreateOrderParam param = new CreateOrderParam();

            string orderRef = order.TransferNumber;
            param.token = token;

            decimal totalGoodValue = goods.Sum(g => g.Quantity * g.DeclareFee);
            string mixedCnName = CreateMixCnName(goods, 64);
            string mixedEnName = CreateMixEnName(goods, 64);
            int totalGoodsQty = goods.Sum(g => g.Quantity);

            var streets = order.ReceiverStreet.ToArray(35);
            var street1 = streets[0];
            var street2 = streets.Length > 1 ? streets[1] : "";

            int orderWeight_g = order.OPWeight == 0 ? goods.Sum(g => g.Weight) : order.OPWeight;
            decimal orderWeight_kg = 0m;
            if (orderWeight_g <= 0)
                throw new Exception("错误:订单重量不能为零");
            else
            {
                orderWeight_kg = orderWeight_g / 1000m;
            }

            OrdersItem orderInfo = new OrdersItem
            {
                countryCode = order.ReceiverCountryCode,
                declaredAmount = totalGoodValue,
                declaredCnname = mixedCnName,
                declaredEnname = mixedEnName,
                declaredNumber = totalGoodsQty,
                orderId = orderRef,
                productCode = productCode,
                receiveCity = order.ReceiverCity,
                receiveEmail = order.ReceiverEmail ?? "",
                receiveFamilyName = "",
                receiveFirstName = order.ReceiverName,
                receiveMobile = order.ReceiverPhone ?? "",
                receiveRoom = "",
                receiveState = order.ReceiverState,
                receiveStreet = street1,
                receiveStreet2 = street2,
                receiveZip = order.ReceiverZipCode,
                sendCity = channel.SenderCity,
                sendEmail = channel.SenderEmail ?? "",
                sendFamilyName = "",
                sendFirstName = channel.SenderName ?? "",
                sendMobile = channel.SenderPhone ?? "",
                sendRoom = "",
                sendState = channel.SenderState ?? "",
                sendStreet = channel.SenderStreet ?? "",
                sendZip = channel.SenderZipCode ?? "",
                sendStreet2 = "",
                sku = "",//如果您的sku需要展示在⾯单上，您可以传给我们，但是我们系统不⽀持sku含特殊字符（包括中⽂），字符⻓度不能超过30 ，如果过⻓，请截断。
                weightkg = orderWeight_kg,
            };


            param.orders = new List<OrdersItem> { orderInfo };
            return param;
        }

        private string CreateMixCnName(List<Order_OrderGoods> goods, int maxLen)
        {
            string allName = string.Join(",", goods.Select(i => i.CnName));
            if (allName.Length > maxLen)
            {
                allName = allName.Substring(0, maxLen);
            }
            return allName;
        }
        private string CreateMixEnName(List<Order_OrderGoods> goods, int maxLen)
        {
            string allName = string.Join(",", goods.Select(i => i.EnName));
            if (allName.Length > maxLen)
            {
                allName = allName.Substring(0, maxLen);
            }
            return allName;
        }

        string MapCodeError(string code)
        {
            switch (code)
            {
                case "500":
                    return "token有问题";
                case "400":
                    return "orderToken有问题，或者orderId有问题";
                case "401":
                    return "订单不存在";
                case "403":
                    return "订单⾮法";
                case "504":
                    return "⾯单号还没好";
                case "505":
                    return "⾯单pdf还没好";
                default: return null;
            }
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            int retryCount = 3;
            for (var count = 1; count <= retryCount; count++)
            {
                string orderId = order.TransferNumber;
                string token = GetToken(channel);
                var labelParam = new LabelRequest { orderId = orderId, orderToken = result.ServiceOrderNumber, token = token, withPdfBase64 = "yes" };
                LabelResponse resp = await InvokeApi<LabelResponse>("/api/open/customer/pull_label", channel, labelParam);

                if (resp != null && resp.data?.Any() == true)
                {
                    if (resp.error || resp.code != "2000")
                    {
                        string msg = resp.message;
                        msg += MapCodeError(resp.code);
                        throw new Exception($"错误:获取面单API返回返回错误:{msg}");
                    }
                    else
                    {
                        var labelData = resp.data.First();
                        if (string.IsNullOrEmpty(labelData.pdfBase64))
                        {
                            throw new Exception($"错误:获取面单API返回返回错误:面单数据为空");
                        }
                        else
                        {
                            //order.TrackingNumber = labelData.labelCode;
                            await _orderRepository.AddChannelOrderInfoRecord(channel.Id, labelData.labelCode, order.TransferNumber);
                            var bytes = Convert.FromBase64String(labelData.pdfBase64);
                            //var bytes = System.Text.Encoding.UTF8.GetBytes(labelData.pdfBase64);
                            //File.WriteAllBytes($"d:\\{labelData.labelCode}.pdf", bytes);
                            return bytes;
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(resp?.message) && resp.message.Contains("label code not maked yet", StringComparison.OrdinalIgnoreCase))
                {

                }
                else
                {

                    string msg = resp.message ?? "错误:获取面单API返回数据为空";
                    throw new Exception(msg);
                }
            }
            throw new Exception($"已重试{retryCount}次仍不能获取面单");
        }



        private async Task<T> InvokeApi<T>(string url, Logistics_Channel channel, object param)
        {
            RestClient client = new RestClient(channel.ApiHost);
            RestRequest request = new RestRequest(url, Method.POST);
            request.AddJsonBody(param);
            var resp = await client.ExecuteAsync<T>(request);
            CheckHttpResponseError(resp);
            return resp.Data;
        }

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