using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.Core.Standard.ExtendMethods;
using XYY.Model.Standard.Channel;
using XYY.Model.Standard.Order;
using XYY.Service.Standard.ChannelApi.Base;
using Dapper;
using XYY.Data.Standard.Finance;

namespace XYY.Service.Standard.ChannelApi.XinZhiHui
{
    public class Api : IBaseApi
    {
        public string ServiceName => "XinZhiHui";
        private IUnitOfWork _unitOfWork;
        private IFinance_CustomerRateRepository _customerRateRepository;
        public Api( IUnitOfWork unitOfWork, IFinance_CustomerRateRepository customerRateRepository)
        {
            _unitOfWork = unitOfWork;
            _customerRateRepository = customerRateRepository;
        }
        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)
        {
            var streetArray = order.ReceiverStreet.ToArray(35);
            if (streetArray.Length > 3)
                throw new Exception("收件人地址超长");
            //如果包含订单信息
            if (!order.TrackingNumber.StartsWith("XYY"))
            {
                return new UploadResult
                {
                    TrackingNumber = order.TrackingNumber,
                    ServiceOrderNumber = order.ServicesOrderNo,
                    IsSuccess = true,
                    DownloadUrl = "true",
                };
            }
            int exportwith = arg.Order.DeclarationMethod == "买单报关" || arg.Order.DeclarationMethod == "无" ? 1 : 2;
            #region 渠道NZ-EUR-BS id 336特殊判断
            if (order.ChannelId == 336)//NZ-EUR-BS
            {
                exportwith = exportwith == 1 ? 0 : exportwith;
                DateTime nowTime = DateTime.Now.Date;
                //汇率转换操作
                var rate = (await _customerRateRepository.QueryBySqlAsync($"select * from Finance_CustomerRate where Currency='EUR' and StartDate<='{nowTime}' and EndDate>='{nowTime}'")).FirstOrDefault();
                foreach (var item in arg.Order.Boxs)
                {
                    item.Goods = await CurrencyCheck(item.Goods, order.SystemNo, rate);
                }
            }
            #endregion

            OrderRequest orderRequest = new OrderRequest
            {
                validation = new Validation
                {
                    access_token = channel.ApiKey
                },
                shipment = new Shipment
                {
                    service = channel.ServiceChannelCode,
                    client_reference = order.CustomerOrderNo,
                    parcel_count = arg.Order.BoxQty,
                    exportwith = exportwith,
                    attrs =await AttrsCheck(arg.Order.Boxs),//属性校验 获取
                    declaration_currency = arg.Order.Boxs.First()?.Goods?.FirstOrDefault()?.Currency,
                    to_address = new To_address
                    {
                        name = order.ReceiverName,
                        company = order.ReceiverCompany,
                        tel = order.ReceiverPhone,
                        address_1 = streetArray[0],
                        address_2 = streetArray.Length > 1 ? streetArray[1] : "",
                        address_3 = streetArray.Length > 2 ? streetArray[2] : "",
                        city = order.ReceiverCity,
                        state = order.ReceiverState,
                        country = order.ReceiverCountryCode,
                        postcode = order.ReceiverZipCode,
                        email = order.ReceiverEmail
                    },
                    parcels = arg.Order.Boxs.Select(x => new ParcelsItem
                    {
                        number = x.BoxNumber,
                        client_width = x.OpWidth.ToString(),
                        client_height = x.OpHeight.ToString(),
                        client_length = x.OpLength.ToString(),
                        client_weight = x.OpInputWeight.ToString(),
                        declarations = x.Goods.Select(y => new DeclarationsItem
                        {
                            name_zh = y.CnName,
                            name_en = y.EnName,
                            unit_value = y.GoodsValue.ToString(),
                            qty = y.Quantity,
                            material = y.Meterial,
                            usage = y.Usage,
                            brand = y.Brand,
                            brand_type = string.Empty,
                            model = y.ModelNumber,
                            sale_price = (order.ChannelId == 336 &&(y.SalePrice??0)==0)? y.GoodsValue : (y.SalePrice ?? 0),
                            sale_url = y.SaleLink,
                            weight = y.Weight,
                            photos = y.SaleLink,
                            hscode = y.HsCode,
                            photo_url = y.SaleLink,
                            is_battery=y.Electric?1:0,
                            is_magnetic=y.Magnetic?1:0,
                        }).ToList()

                    }).ToList()
                }
            };
            RestSharp.RestClient client = new RestSharp.RestClient(channel.ApiHost);
            RestSharp.RestRequest request = new RestSharp.RestRequest("api/v4/shipment/create", RestSharp.Method.POST);
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(orderRequest);
            request.AddJsonBody(json);
            var response = client.Execute(request);
            if (response.StatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商下单失败{response.Content ?? response.ErrorMessage}");
            try
            {
                var r = Newtonsoft.Json.JsonConvert.DeserializeObject<OrderResult>(response.Content);
                if (r.status != 1)
                    throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商下单失败{r.info}");
                return new UploadResult
                {
                    IsSuccess = true,
                    TrackingNumber = r.data.shipment.shipment_id
                };
            }
            catch (Exception ex)
            {
                throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商下单失败{response.Content ?? response.ErrorMessage}");
            }
        }

        public async Task<byte[]> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> orderGoods)
        {
            if (result.DownloadUrl != "true")
                return null;
            string action = "api/v4/shipment/get_labels";
            RestSharp.RestClient client = new RestSharp.RestClient(channel.ApiHost);
            RestSharp.RestRequest request = new RestSharp.RestRequest(action, RestSharp.Method.POST);
            var req = new
            {
                validation = new
                {
                    access_token = channel.ApiKey,
                    shipment = new
                    {
                        shipment_id = result.TrackingNumber
                    }
                }
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(req);
            request.AddJsonBody(json);
            var response = client.Execute(request);
            if (response.StatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商面单下单失败{response.Content ?? response.ErrorMessage}");
            try
            {
                var r = Newtonsoft.Json.JsonConvert.DeserializeObject<LabelRoot>(response.Content);
                if (r.status != 1)
                    throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商面单下单失败{r.info}");
                result.MPSTrackings = r.data.shipment.parcels.ToDictionary(x => x.tracking_number, y => y.item_number);
                byte[] data = null;
                for (int i = 0; i < 5; i++)
                {
                    System.Net.WebClient webClient = new System.Net.WebClient();
                    data = webClient.DownloadData(r.data.shipment.single_pdf);
                    if (data.Length > 5 * 1024)
                        return data;
                    //每三秒重试
                    System.Threading.Thread.Sleep(3 * 1000);
                }
                throw new Exception($"面单下载失败{r.data.shipment.single_pdf}");
            }
            catch (Exception ex)
            {
                throw new Exception($"Number{order.CustomerOrderNo};{order.SystemNo}服务商面单下单失败{response.Content ?? response.ErrorMessage}");
            }

        }

        public async Task<string> GetTrackingNumber(string SystemNo, string TrackingNumber, string ServiceOrderNo, Logistics_Channel channel)
        {
            string action = "api/v5/shipment/get_tracking_numbers";
            RestSharp.RestClient client = new RestSharp.RestClient(channel.ApiHost);
            RestSharp.RestRequest request = new RestSharp.RestRequest(action, RestSharp.Method.POST);
            request.AddHeader("Authorization", $"Bearer {channel.ApiKey}");
            TrackingNumbersBody trackingNumbersBody = new TrackingNumbersBody() { shipment=new TrackingNumbersBodyShipment() { shipment_id=TrackingNumber} };
            request.AddJsonBody(trackingNumbersBody);
            var response = client.Execute(request);
            if (response.StatusCode != System.Net.HttpStatusCode.OK)
                throw new Exception($"{SystemNo}获取个跟踪单号失败{response.Content ?? response.ErrorMessage}");
            try
            {
                var r = Newtonsoft.Json.JsonConvert.DeserializeObject<TrackingNumbersResult>(response.Content);
                if (r.status != 1)
                    throw new Exception($"{SystemNo}获取个跟踪单号失败{r.info}");

                return r.data.shipment.tracking_number;
            }
            catch (Exception ex)
            {
                throw new Exception($"{SystemNo}获取个跟踪单号失败{response.Content ?? response.ErrorMessage}");
            }
        }
        /// <summary>
        /// 申报币种问题判断
        /// </summary>
        /// <param name="goods"></param>
        private async Task<List<Model.Standard.MpsOrder.Order_MpsOrderGoods>> CurrencyCheck(List<Model.Standard.MpsOrder.Order_MpsOrderGoods> goods,string SystemNo, Model.Standard.Finance.Finance_CustomerRate rate)
        {
            if(goods.Where(x=>x.Currency== "EUR").Count() == goods.Count){ return goods; }
            bool isChange = false;string DeclareCurrency=string.Empty;
            if (goods.Where(x => x.Currency == "CNY" || x.Currency == "RMB").Count() == goods.Count)
            {
                isChange = true; DeclareCurrency = "CNY";
            }
            else if (goods.Where(x => x.Currency == "USD").Count() == goods.Count)
            {
                isChange = true; DeclareCurrency = "USD";
            }
            else
            {
                throw new Exception("请传入一致的币种，CNY或USD");
            }
            if (isChange)
            {
                if (rate==null) { throw new Exception($"没有EUR相匹配的客户汇率！请联系财务完善！"); }

                goods.ForEach(x => {
                    x.Currency = "EUR";
                    x.GoodsValue = DeclareCurrency == "CNY" ? (decimal.Round(x.GoodsValue /rate.ToCNY,2)) : (decimal.Round(x.GoodsValue / rate.ToUSD,2));
                });

                var model = goods.Select(x => new Order_ApiDeclaration
                {
                    GoodsId = x.Id,
                    OriginDeclareFee = x.GoodsValue,
                    ChannelId = 0,
                    OrderDeclareValue =x.GoodsValue * x.Quantity,
                    CnName = x.CnName,
                    EnName = x.EnName,
                    DeclareValue = x.GoodsValue,
                    SystemNo = SystemNo,
                    CreateTime = DateTime.Now,
                    CreateUserName = string.Empty,
                    Guid = "",
                    Qty = x.Quantity,
                    Remark=x.Currency,
                }).ToList();

                var list = await _unitOfWork.QueryAsync<Order_ApiDeclaration>(x => x.SystemNo == SystemNo);
                var ids = list?.Select(i => i.Id);
                if (ids?.Any() == true)
                {
                    await _unitOfWork.ExecuteAsync($"delete Order_ApiDeclaration where id in @ids", new { ids = ids });
                }
                await _unitOfWork.BulkToDBAsync<Order_ApiDeclaration>(model);
            }
            return goods;
        }
        private async Task<List<string>> AttrsCheck(List<Model.Standard.MpsOrder.Order_MpsOrderBox> Boxs)
        {
            var attrs = new List<string>();
            foreach (var item in Boxs)
            {
                if (item.Goods.Any(x=>x.Magnetic==true)) { attrs.Add("magnetic"); }
                if (item.Goods.Any(x => x.Electric == true)) { attrs.Add("elec"); }
            }
            attrs = attrs.Distinct().ToList();
            return attrs;
        }
    }
}
