using BBWYB.Common.Http;
using com.alibaba.openapi.client;
using com.alibaba.openapi.client.entity;
using com.alibaba.openapi.client.policy;
using Newtonsoft.Json.Linq;
using SDKAdapter.PurchasePlatform.Models;

namespace SDKAdapter.PurchasePlatform.Client
{
    public class PP_1688Client : PP_PlatformClient
    {
        public override AdapterEnums.PlatformType Platform => AdapterEnums.PlatformType.阿里巴巴;

        private _1688TradeTypeCompare _1688TradeTypeCompare;
        public PP_1688Client(RestApiService restApiService) : base(restApiService)
        {
            _1688TradeTypeCompare = new _1688TradeTypeCompare();
        }

        private SyncAPIClient GetSyncAPIClient(string appKey, string appSecret)
        {
            return new SyncAPIClient(appKey, appSecret, restApiService);
        }

        public override PP_PreviewOrderResponse PreviewOrder(PP_PreviewOrderRequest request)
        {
            var client = GetSyncAPIClient(request.AppKey, request.AppSecret);
            RequestPolicy reqPolicy = new RequestPolicy();
            reqPolicy.HttpMethod = "POST";
            reqPolicy.NeedAuthorization = false;
            reqPolicy.RequestSendTimestamp = false;
            reqPolicy.UseHttps = false;
            reqPolicy.UseSignture = true;
            reqPolicy.AccessPrivateApi = false;

            Request _request = new Request();
            APIId apiId = new APIId();
            apiId.Name = "alibaba.createOrder.preview";
            apiId.NamespaceValue = "com.alibaba.trade";
            apiId.Version = 1;
            _request.ApiId = apiId;

            var param = new CreateOrderPreview()
            {
                addressParam = new AddressParam()
                {
                    fullName = request.Consignee.ContactName,
                    mobile = request.Consignee.Mobile,
                    phone = request.Consignee.TelePhone,
                    postCode = "000000",
                    address = request.Consignee.Address,
                    provinceText = request.Consignee.Province,
                    cityText = request.Consignee.City,
                    areaText = request.Consignee.County,
                    townText = request.Consignee.Town
                },
                cargoParamList = new List<CargoParam>(),
                flow = request.PurchaseMode == AdapterEnums.PurchaseMode.批发 ? "general" : "saleproxy"
            };
            foreach (var cargo in request.OrderProductParamList)
            {
                param.cargoParamList.Add(new CargoParam()
                {
                    offerId = long.Parse(cargo.ProductId),
                    specId = cargo.SpecId,
                    quantity = cargo.Quantity
                });
            }
            _request.RequestEntity = param;
            if (!string.IsNullOrEmpty(request.AppToken))
                _request.AccessToken = request.AppToken;
            JObject result = null;
            try
            {
                result = client.NewRequest(_request, reqPolicy);
                if (result.Value<bool>("success") != true)
                    throw new Exception(result.Value<string>("errorMsg"));
            }
            catch (Exception ex)
            {
                throw;
            }

            var orderPreviewResuslt = (JArray)result["orderPreviewResuslt"];
            List<JToken> intersectTradeModeList = new List<JToken>();

            foreach (var orderPreviewJToken in orderPreviewResuslt)
            {
                if (orderPreviewJToken["tradeModelList"] == null)
                    throw new Exception("当前交易不可通过API下单,请使用1688网页交易 [交易模式列表为空]");
                var tradeModeJArray = ((JArray)orderPreviewJToken["tradeModelList"]).Where(tradeJToken => tradeJToken.Value<bool>("opSupport"));
                if (tradeModeJArray.Count() == 0)
                    throw new Exception("当前交易不可通过API下单,请使用1688网页交易 [没有支持开放平台下单的交易模式]");

                if (intersectTradeModeList.Count() == 0)
                    intersectTradeModeList.AddRange(tradeModeJArray);
                else
                    intersectTradeModeList = intersectTradeModeList.Intersect(tradeModeJArray, _1688TradeTypeCompare).ToList();
            }

            if (intersectTradeModeList.Count() == 0)
                throw new Exception("当前交易不可通过API下单,请使用1688网页交易 [多个拆单之间没有相同的交易模式]");
            return new PP_PreviewOrderResponse()
            {
                FreightAmount = orderPreviewResuslt.Sum(jt => jt.Value<decimal>("sumCarriage")) / 100M,
                ProductAmount = orderPreviewResuslt.Sum(jt => jt.Value<decimal>("sumPaymentNoCarriage")) / 100M,
                TotalAmount = orderPreviewResuslt.Sum(jt => jt.Value<decimal>("sumPayment")) / 100M,
                Extensions = intersectTradeModeList.FirstOrDefault().Value<string>("tradeType")
                //OrderTradeType = new OrderTradeTypeResponse()
                //{
                //    Code = intersectTradeModeList.First().Value<string>("tradeType"),
                //    Name = intersectTradeModeList.First().Value<string>("name"),
                //}
            };
        }

        public override PP_CreateOrderResponse CreateOrder(PP_CreateOrderRequest request)
        {
            var client = GetSyncAPIClient(request.AppKey, request.AppSecret);
            RequestPolicy reqPolicy = new RequestPolicy();
            reqPolicy.HttpMethod = "POST";
            reqPolicy.NeedAuthorization = false;
            reqPolicy.RequestSendTimestamp = false;
            reqPolicy.UseHttps = false;
            reqPolicy.UseSignture = true;
            reqPolicy.AccessPrivateApi = false;

            Request _request = new Request();
            APIId apiId = new APIId
            {
                Name = "alibaba.trade.fastCreateOrder",
                NamespaceValue = "com.alibaba.trade",
                Version = 1
            };
            _request.ApiId = apiId;

            var param = new
            {
                flow = request.PurchaseMode == AdapterEnums.PurchaseMode.批发 ? "general" : "saleproxy",
                message = request.Remark,
                addressParam = new
                {
                    fullName = request.Consignee.ContactName,
                    mobile = request.Consignee.Mobile,
                    phone = request.Consignee.Mobile,
                    cityText = request.Consignee.City,
                    provinceText = request.Consignee.Province,
                    areaText = request.Consignee.County,
                    townText = request.Consignee.Town,
                    address = request.Consignee.Address
                },
                cargoParamList = request.OrderProductParamList.Select(cargo => new
                {
                    offerId = long.Parse(cargo.ProductId),
                    specId = cargo.SpecId,
                    quantity = cargo.Quantity
                }),
                tradeType = request.Extensions
            };

            _request.RequestEntity = param;
            if (!string.IsNullOrEmpty(request.AppToken))
                _request.AccessToken = request.AppToken;
            var result = client.NewRequest(_request, reqPolicy);
            if (result.Value<bool>("success") != true)
            {
                throw new Exception(result.ToString());
            }

            var totalSuccessAmount = result["result"].Value<long>("totalSuccessAmount") / 100M; //采购单总金额,单位分
            var purchaseOrderId = result["result"].Value<string>("orderId"); //采购单号
            var postFee = result["result"].Value<long>("postFee") / 100M;  //采购单运费,单位分
            var purchaseAmount = totalSuccessAmount - postFee;  //采购成本

            var failedOfferJArray = result["failedOfferList"] != null ? (JArray)result["failedOfferList"] : null;
            //if (failedOfferJArray != null)
            //{
            //    var failOrderStringBuilder = new StringBuilder();
            //    foreach (var failedOfferJToken in failedOfferJArray)
            //        failOrderStringBuilder.AppendLine(failedOfferJToken.ToString());
            //    var ex = new Exception(failOrderStringBuilder.ToString());
            //    nLogManager.Default().Error(ex, $"下单部分商品失败 采购单Id{purchaseOrderId} 请求参数{JsonConvert.SerializeObject(request)}");
            //}

            return new PP_CreateOrderResponse()
            {
                TotalAmount = totalSuccessAmount,
                ProductAmount = purchaseAmount,
                FreightAmount = postFee,
                OrderId = purchaseOrderId,
                IsPay = false,
                FailProductMessageList = failedOfferJArray == null ? null : failedOfferJArray.Select(failedOfferJToken => failedOfferJToken.ToString()).ToList()
            };
        }

        public override PP_QueryOrderDetailResponse QueryOrderDetail(PP_QueryOrderDetailRequest request)
        {
            var client = GetSyncAPIClient(request.AppKey, request.AppSecret);
            RequestPolicy reqPolicy = new RequestPolicy();
            reqPolicy.HttpMethod = "POST";
            reqPolicy.NeedAuthorization = false;
            reqPolicy.RequestSendTimestamp = false;
            reqPolicy.UseHttps = false;
            reqPolicy.UseSignture = true;
            reqPolicy.AccessPrivateApi = false;

            Request _request = new Request();
            APIId apiId = new APIId
            {
                Name = "alibaba.trade.get.buyerView",
                NamespaceValue = "com.alibaba.trade",
                Version = 1
            };
            _request.ApiId = apiId;

            var param = new
            {
                webSite = "1688",
                orderId = request.OrderId,
                includeFields = "baseInfo,productItems"
            };
            _request.RequestEntity = param;
            if (!string.IsNullOrEmpty(request.AppToken))
                _request.AccessToken = request.AppToken;
            var result = client.NewRequest(_request, reqPolicy);
            if (result.Value<bool>("success") != true)
                throw new Exception(result.Value<string>("errorMessage"));


            return new PP_QueryOrderDetailResponse()
            {
                OrderId = request.OrderId,
                FreightAmount = result["result"]["baseInfo"].Value<decimal>("shippingFee"),
                ProductAmount = result["result"]["baseInfo"].Value<decimal>("totalAmount") - result["result"]["baseInfo"].Value<decimal>("shippingFee"),
                TotalAmount = result["result"]["baseInfo"].Value<decimal>("totalAmount"),
                ItemList = result["result"]["productItems"].Select(itemJToken => new PP_QueryOrderDetailSkuResponse()
                {
                    ProductId = itemJToken.Value<string>("productID"),
                    SkuId = itemJToken.Value<string>("skuID"),
                    SpecId = itemJToken.Value<string>("specId"),
                    ProductAmount = itemJToken.Value<decimal>("itemAmount"),
                    Quantity = Convert.ToInt32(itemJToken.Value<decimal>("quantity")),
                    Price = itemJToken.Value<decimal>("price")
                }).ToList()
            };
        }

        public override PP_QueryOrderLogisticsResponse QueryOrderLogistics(PP_QueryOrderLogisticsRequest request)
        {
            var client = GetSyncAPIClient(request.AppKey, request.AppSecret);
            RequestPolicy reqPolicy = new RequestPolicy();
            reqPolicy.HttpMethod = "POST";
            reqPolicy.NeedAuthorization = false;
            reqPolicy.RequestSendTimestamp = false;
            reqPolicy.UseHttps = false;
            reqPolicy.UseSignture = true;
            reqPolicy.AccessPrivateApi = false;

            Request _request = new Request();
            APIId apiId = new APIId();
            apiId.Name = "alibaba.trade.getLogisticsInfos.buyerView";
            apiId.NamespaceValue = "com.alibaba.logistics";
            apiId.Version = 1;
            _request.ApiId = apiId;

            var param = new { orderId = request.OrderId, webSite = "1688", fields = "logisticsCompanyId,logisticsCompanyName,logisticsBillNo" };
            _request.RequestEntity = param;
            if (!string.IsNullOrEmpty(request.AppToken))
                _request.AccessToken = request.AppToken;
            var result = client.NewRequest(_request, reqPolicy);
            if (result.Value<bool>("success") != true)
                throw new Exception(result.Value<string>("errorMessage"));

            //nLogManager.Default().Info($"GetWayBillNoByOrderId QueryOrderWayBillNoRequest {JsonConvert.SerializeObject(queryOrderWayBillNoRequest)} Result {result}");

            var firstJToken = result["result"].FirstOrDefault();
            return new PP_QueryOrderLogisticsResponse()
            {
                ExpressId = firstJToken.Value<string>("logisticsCompanyId"),
                ExpressName = firstJToken.Value<string>("logisticsCompanyName"),
                WayBillNo = firstJToken.Value<string>("logisticsBillNo")
            };
        }
    }

    public class _1688TradeTypeCompare : IEqualityComparer<JToken>
    {
        public bool Equals(JToken x, JToken y)
        {
            return x.Value<string>("tradeType").Equals(y.Value<string>("tradeType"));
        }

        public int GetHashCode(JToken obj)
        {
            return obj.GetHashCode();
        }
    }
}