using Dapper;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using XYY.Data.Standard.Order;
using XYY.Model.Standard.Order;
using System.Linq;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Model.Standard.Channel;
using System.Diagnostics;
using XYY.Service.Standard.ChannelApi;
using XYY.Api.Order.Model.Order;
using XYY.Common.Standard;
using XYY.Service.Standard.ChannelApi.Out;
using System.Text;
using XYY.Data.Standard.Channel;
using XYY.Core.Standard.Data.Infrastructure;
using System.Data.SqlClient;
using XYY.Data.Standard.Logistics;
using XYY.Model.Standard.Logistics;
using XYY.Service.Standard.Channel;
using XYY.Service.Standard.Customer;
using XYY.Model.Standard.Dto.order;
using System.Threading.Channels;
using Org.BouncyCastle.Ocsp;
using iTextSharp.text;
using XYY.Service.Standard.ChannelApi.Winit.ISPApi;
using Org.BouncyCastle.Asn1.X509;

namespace XYY.Service.Standard.Order
{
    public class OrderService : IOrderService
    {

        private IOrderRepository _orderRepository;
        private IOrderGoodsRepository _orderGoodsRepository;
        private IExcelHelper _excelHelper;
        private ILogger<OPTHOrderModel> _logger;
        private IEnumerable<IBaseApi> _baseApis;
        private IEnumerable<IGetTrackingNumberApi> _getTrackingApi;
        private ILogger<UploadResult> _dataUpdateLogger;
        private ILogistics_BoxRepository _boxRepository;
        private ILogistics_BoxDetailRepository _BoxDetailRepository;
        readonly ILogistics_ChannelRepository _channelRepository;
        private IJobMessageRepository _jobMessageRepository;
        private IAlterExpressNoLogRepository _alterExpressNoLogRepository;
        private Ilogistics_ChannelCancelRepository _ChannelCancelRepository;
        private IUnitOfWork _unitOfWork;
        private IEnumerable<IUItidelApi> _packLabelApis;
        private ILogistics_IBBagLabelRepository _IBBagLabelRepository;
        private readonly ICustomerService _customerService;
        private readonly IChannelService _channelService;
        private readonly IMoreThanOneTicketService _moreThanOneTicketService;
        private IOrderUnusualReasonRepository _orderUnusualReasonRepository;

        private static List<int> alterDeclareValChannelIds = new List<int> {
            313,
            230,
            346,
            340,
            342,
            390,
            288,
            289,
            385,
            386,
            411,
            447,
            448,
            458,
            471,
            544,
            561,
            566,
        };

        private static List<int> alterNotIossDeDeclearValueChannelIds = new List<int>
        {
            550,
            549,
            538,
            537
        };

        private static List<int> alterNotIossDeDeclearValueCustomerIds = new List<int>
        {1,
            372
        };

        public OrderService(IOrderRepository orderRepository, IExcelHelper excelHelper, ILogger<OPTHOrderModel> logger,
            IEnumerable<IBaseApi> baseApis, ILogger<UploadResult> dataUpdateLogger, IEnumerable<IConfimApi> confimApi,
            ILogistics_ChannelRepository channelRepository, ILogistics_BoxRepository boxRepository, IEnumerable<IGetTrackingNumberApi> getTrackingApi,
            IJobMessageRepository jobMessageRepository, IAlterExpressNoLogRepository alterExpressNoLogRepository, Ilogistics_ChannelCancelRepository ChannelCancelRepository,
            IUnitOfWork unitOfWork, ILogistics_BoxDetailRepository BoxDetailRepository,
            IEnumerable<IUItidelApi> packLabelApis,
            ILogistics_IBBagLabelRepository IBBagLabelRepository,
            IOrderGoodsRepository orderGoodsRepository
            , IChannelService channelService
            , ICustomerService customerService
            , IMoreThanOneTicketService moreThanOneTicketService,
            IOrderUnusualReasonRepository orderUnusualReasonRepository
            )
        {
            _orderGoodsRepository = orderGoodsRepository;
            _orderRepository = orderRepository;
            _excelHelper = excelHelper;
            _logger = logger;
            _baseApis = baseApis;
            _dataUpdateLogger = dataUpdateLogger;
            _channelRepository = channelRepository;
            _boxRepository = boxRepository;
            _getTrackingApi = getTrackingApi;
            _jobMessageRepository = jobMessageRepository;
            _alterExpressNoLogRepository = alterExpressNoLogRepository;
            _ChannelCancelRepository = ChannelCancelRepository;
            _unitOfWork = unitOfWork;
            _BoxDetailRepository = BoxDetailRepository;
            _packLabelApis = packLabelApis;
            _IBBagLabelRepository = IBBagLabelRepository;
            _channelService = channelService;
            _customerService = customerService;
            _moreThanOneTicketService = moreThanOneTicketService;
            _orderUnusualReasonRepository = orderUnusualReasonRepository;
        }

        /// <summary>
        /// 生成箱子编码(流水号)
        /// </summary>
        /// <returns></returns>
        public string GenerateBoxNumber()
        {
            int systemId = 2;
            string key = "B" + DateTime.Now.ToString("yyMMdd");
            int count = _channelRepository.GetPackagePrintQty(key);
            return $"{key}{(count).ToString("0000")}{systemId.ToString("00")}";
        }

        public async Task<PageResult<BagDeclareLog>> GetBagDeclareLogs(QueryModel queryModel)
        {
            return await _orderRepository.GetBagDeclareLogs(queryModel);
        }
        public async Task CancelOrders(List<string> SystemNos, Logistics_Channel channel)
        {
            var baseApi = _baseApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
            baseApi.CannelOrders(SystemNos);
            if (channel.PublicName.StartsWith("W-"))
            {
                string sql = "delete WinitOrderInfo where TransferNumber in @TransferNumber ";
                await _unitOfWork.ExecuteAsync(sql, new { TransferNumber = SystemNos });
            }
        }
        /// <summary>
        /// 改为mq执行，这里的方法暂不使用
        /// </summary>
        /// <param name="SystemNos"></param>
        /// <returns></returns>
        public async Task CancelOrdersByNoStr(List<string> allSysmteNos)
        {
            var batchQty = 1000.0;
            int UserId = _unitOfWork.CurrentId ?? 0;
            for (int i = 0; i < Math.Ceiling(allSysmteNos.Count() / batchQty); i++)
            {
                var tempSysmteNos = allSysmteNos.Skip(i * (int)batchQty).Take((int)batchQty).ToList();
                string sql = @$"select a.Id Order_OrderId,a.TrackingNumber,a.SystemNo,b.ServiceCode,b.PublicName,b.ApiHost,b.ApiKey,b.ApiSecret,{UserId} OperationUserId from Order_Order a
join Logistics_Channel b on b.Id=a.ChannelId
where a.OrderStatus<3 and a.SystemNo in @SystemNo";//小于三属于未装箱数据，才可以取消
                List<logistics_ChannelCancel> logistics_ChannelCancels = (await _ChannelCancelRepository.QueryAsync<logistics_ChannelCancel>(sql,
                        new { SystemNo = tempSysmteNos })).ToList();
                foreach (var item in logistics_ChannelCancels)
                {
                    try
                    {
                        var baseApi = _baseApis.Where(x => x.ServiceName == item.ServiceCode).FirstOrDefault();
                        baseApi.CannelOrdersByModel(item);
                        item.ResultState = ResultStateEnum.成功.GetValue();
                    }
                    catch (Exception ex)
                    {
                        item.ResultState = ResultStateEnum.异常.GetValue(); item.ResultMessage = ex.Message;
                        continue;//异常进行下一个,记录以数据表为准
                    }
                }
                //1K 数据插入一次
                if (logistics_ChannelCancels.Count > 0)
                {
                    await _ChannelCancelRepository.BulkToDBAsync(logistics_ChannelCancels);
                    //更新处理成功的数据
                    var tempOrder_OrderId = logistics_ChannelCancels.Where(x => x.ResultState == ResultStateEnum.成功.GetValue()).Select(x => x.Order_OrderId).ToList();

                    string deleteUnususalReasonSql = $"delete Order_UnusualReason where OrderId in ({string.Join(",", tempOrder_OrderId)})";
                    await _orderRepository.ExecuteSqlNotTransferAsync(deleteUnususalReasonSql.TrimEnd(','));

                    DateTime dateTime = DateTime.Now;
                    string OperationUserName = _unitOfWork.CurrentName;
                    List<Order_UnusualReason> order_Unusuals = new List<Order_UnusualReason>();
                    foreach (var item in tempOrder_OrderId)
                    {
                        Order_UnusualReason order_Unusual = new Order_UnusualReason
                        {
                            OrderId = item,
                            UnusualReason = UnusualReasonType.渠道面单已手动取消,
                            CreateTime = dateTime,
                            CreateUserName = OperationUserName,
                            UpdateTime = dateTime,
                            UpdateUserName = OperationUserName,
                        };
                        order_Unusuals.Add(order_Unusual);
                    }
                    await _orderUnusualReasonRepository.BulkToDBAsync(order_Unusuals);
                }
            }
        }
        public async Task<List<dynamic>> GetZZESBUpdateData(string lading)
        {
            return await _orderRepository.GetZZESBUpdateData(lading);
        }

        public async Task<UploadResult> DataUpload(Order_Order order, List<Order_OrderGoods> goods, Logistics_Channel channel, ExtendArg arg)
        {
            Stopwatch watch = new Stopwatch();
            var baseApi = _baseApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
            if (baseApi == null)
            {
                _dataUpdateLogger.LogError(channel.ServiceCode + "-" + channel.Id + "未找到服务");
                throw new Exception("未找到相关的API服务");
            }
            else
            {
                try
                {
                    List<Order_ApiDeclaration> apiDeclarations = new List<Order_ApiDeclaration>();
                    if (alterDeclareValChannelIds.Contains(order.ChannelId))
                    {
                        //申报修改
                        decimal declareFee = goods.Sum(x => x.DeclareFee);
                        if (declareFee < 800)
                        {
                            decimal rate = 0.4m;
                            if (declareFee * (1 + rate) >= 800)
                            {
                                //申报价格不可大于 800 USD
                                //重新计算比例(两位)
                                rate = Math.Floor((780 / declareFee - 1) * 100) / 100;
                            }
                            //申报价值增加

                            goods.ForEach(x =>
                            {
                                x.Guid = Guid.NewGuid().ToString();
                                x.DeclareFee = x.DeclareFee * (1 + rate);
                            });
                            decimal OrderDeclareValue = goods.Sum(y => y.DeclareFee);
                            goods.ForEach(x =>
                            {
                                apiDeclarations.Add(new Order_ApiDeclaration
                                {
                                    GoodsId = x.Id,
                                    OriginDeclareFee = x.DeclareFee,
                                    SubmitDeclareValue = x.DeclareFee,
                                    ChannelId = order.ChannelId,
                                    CnName = x.CnName,
                                    EnName = x.EnName,
                                    Qty = x.Quantity,
                                    Guid = x.Guid,
                                    DeclareValue = x.DeclareFee,
                                    OrderDeclareValue = OrderDeclareValue,
                                    SystemNo = order.SystemNo,
                                    Remark = "申报上调" + rate
                                });
                            });
                        }
                    }

                    if (alterNotIossDeDeclearValueChannelIds.Contains(order.ChannelId)
                        && alterNotIossDeDeclearValueCustomerIds.Contains(order.CustomerId)
                       && order.CustomerWeight > 3000)
                    {
                        decimal declareFee = goods.Sum(x => x.DeclareFee);
                        if (declareFee < 30)
                        {
                            //申报价格不可大于 800 USD
                            //重新计算比例(两位)
                            decimal rate = Math.Ceiling((30 / declareFee - 1) * 100) / 100;
                            //申报价值增加

                            goods.ForEach(x =>
                            {
                                x.Guid = Guid.NewGuid().ToString();
                                x.DeclareFee = x.DeclareFee * (1 + rate);
                            });
                            decimal OrderDeclareValue = goods.Sum(y => y.DeclareFee);
                            goods.ForEach(x =>
                            {
                                apiDeclarations.Add(new Order_ApiDeclaration
                                {
                                    GoodsId = x.Id,
                                    OriginDeclareFee = x.DeclareFee,
                                    SubmitDeclareValue = x.DeclareFee,
                                    ChannelId = order.ChannelId,
                                    CnName = x.CnName,
                                    EnName = x.EnName,
                                    Qty = x.Quantity,
                                    Guid = x.Guid,
                                    DeclareValue = x.DeclareFee,
                                    OrderDeclareValue = OrderDeclareValue,
                                    SystemNo = order.SystemNo,
                                    Remark = "申报上调" + rate
                                });
                            });
                        }
                    }


                    if (apiDeclarations.Count > 0 && channel.Id != 493)
                    {
                        var list = await _unitOfWork.QueryAsync<Order_ApiDeclaration>(x => x.SystemNo == order.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>(apiDeclarations);
                    }


                    _dataUpdateLogger.LogWarning(baseApi.ServiceName + "-" + channel.Id + "开始下单");
                    watch.Start();
                    var result = await baseApi.DataUpload(order, goods, channel, arg);
                    watch.Stop();
                    if (result.IsSuccess)
                    {
                        _dataUpdateLogger.LogWarning(baseApi.ServiceName + "-" + channel.Id + "下单成功:执行时长{time}，返回结果{@UploadResult}",
                             watch.ElapsedMilliseconds, result);
                    }
                    else
                    {
                        _dataUpdateLogger.LogWarning(baseApi.ServiceName + "-" + channel.Id + "下单失败:执行时长{time} {message}", watch.ElapsedMilliseconds, result.Error);
                    }
                    return result;
                }
                catch (OrderApiException ex)
                {
                    watch.Stop();
                    _dataUpdateLogger.LogError(baseApi.ServiceName + "-" + channel.Id + "下单失败:执行时长{time}，错误明细{@OrderApiException}",
                         watch.ElapsedMilliseconds, ex);

                    return new UploadResult
                    {
                        Error = ex.Message.Replace("fpx", "系统").Replace("4PX", "XYY"),
                        IsSuccess = false
                    };
                }
            }
        }

        public async Task<string> DrawPdfLabel(UploadResult result, Logistics_Channel channel, Order_Order order, List<Order_OrderGoods> goods)
        {
            Stopwatch watch = new Stopwatch();
            var baseApi = _baseApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
            if (baseApi == null)
            {
                _dataUpdateLogger.LogError(channel.ServiceClass + "-" + channel.Id + "未找到服务");
                throw new Exception("未找到相关的API服务");
            }
            else
            {
                try
                {
                    _dataUpdateLogger.LogWarning(baseApi.ServiceName + "-" + channel.Id + "开始下载面单");
                    watch.Start();
                    var data = await baseApi.DrawPdfLabel(result, channel, order, goods);
                    if (data == null)
                        return null;
                    watch.Stop();
                    _dataUpdateLogger.LogWarning(baseApi.ServiceName + "-" + channel.Id + "下载面单成功:执行时长{time}",
                        watch.ElapsedMilliseconds);

                    string base64 = Convert.ToBase64String(data);
                    if (order.ChannelId == 195 && order.CustomerId == 197)
                    {
                        //指定客户，FC运单号有更新时，我们对返回结果做一个特殊处理,TrackingNumber+ Base64
                        return result.TrackingNumber + ";" + base64;
                    }
                    return base64;
                }
                catch (OrderApiException ex)
                {
                    watch.Stop();
                    _dataUpdateLogger.LogError(baseApi.ServiceName + "-" + channel.Id + "下载面单失败:执行时长{time}，错误明细{@OrderApiException}，系统单号{@TrackingNumber}",
                         watch.ElapsedMilliseconds, ex, order.TransferNumber);
                    throw new Exception(ex.Message.Replace("fpx", "系统").Replace("4PX", "XYY"));
                }
            }
        }

        public async Task BagConfimWithAwb(string ladingBillNumber)
        {
            var confirmableServiceChannelCodes = GetBagConfirmChannelCodes();
            var ladingBillServiceChannelCodes = await _orderRepository.GetLadingBillServiceChannelCodes(ladingBillNumber);
            if (ladingBillServiceChannelCodes?.Any() == true)
            {
                List<BagDeclareRequest> reqs = new List<BagDeclareRequest>();
                foreach (var channel in ladingBillServiceChannelCodes)
                {
                    if (confirmableServiceChannelCodes.Contains(channel.ServiceChannelCode))
                    {
                        BagDeclareRequest req = await _orderRepository.GetWaitBoxDeclareRequest(channel.ChannelId, ladingBillNumber);
                        reqs.Add(req);
                    }
                }
                if (reqs.Count > 0)
                {
                    await ConfirmBagByRequest(reqs);
                }
            }
        }

        private string[] GetBagConfirmChannelCodes()
        {
            string[] serviceChannelCodes = new string[] {
                "ACIPS", "ACILW",
                "US Postage Share Services_IB",
                "US Postage Share Services_ALX_ORD",
                "US Postage Share Services_ALX_LAX",
                "US Postage Share Services_ALX_JFK",
                "ISP062917", "ISP062914", "ISP062911",
                "ISP062512","ISP062509","ISP062542","ISP062545","ISP042188","ISP042215",
                "OSF711006598;XYYUS114",
                "OSF711006599;XYYUS114",
                "OSF711006640;XYYUS601",
                "OSF711006642;XYYUS601",
                "OSF711006666;XYYUS900",
                "OSF711006665;XYYUS900",
                "AGS_GSCP",
                "OSF711006788;XY_USPB_90040_90040",
                "OSF711006789;XY_USPB_60491_60491",
                "OSF711006197;XY_USPB_08831_08831" ,
                "OSF711006197;XY_USPB_08831_91748",
                "OSF711006789;XY_USPB_60491_91748",
                "OSF711006788;XY_USPB_90040_91748" ,
                "OSF711007053;XYYUS900",
                "OSF711006666;XYYUS900",
                "OSF711006642;XYYUS601",
                "OSF711007053;XYYUS601",
                "OSF711006599;XYYUS114",
                "OSF711007053;XYYUS114",
                "1941","1821",
                "1901",
                "MBX/IMX","MBR/IMR",//荷兰邮政
                "16",//派送翼ACI预报
                "usps_first_class",//IMG
                "usps_priority_mail",//IMG
                "usps_ga_small",
                "UBI.CNDIRECT2UK.HERMES"
            };
            return serviceChannelCodes;
        }

        public async Task BagConfim()
        {
            var channelServiceCodes = GetBagConfirmChannelCodes();
            var reqs = await _orderRepository.GetWaitBoxDeclareRequest(channelServiceCodes);
            await ConfirmBagByRequest(reqs);
        }

        private async Task ConfirmBagByRequest(List<BagDeclareRequest> reqs)
        {
            foreach (var req in reqs)
            {
                try
                {
                    if (req.BatchDeclare.Count > 0)
                    {
                        List<int> successOrders = new List<int>();
                        List<tempBagDeclareDto> errorOrders = new List<tempBagDeclareDto>();

                        var countryCode = req.BatchDeclare.First().Value.FirstOrDefault()?.CountryCode;
                        req.Country = countryCode;
                        var baseApi = _baseApis.Where(x => x.ServiceName == req.Channel.ServiceCode).FirstOrDefault();
                        var errors = await baseApi.BagDeclare(req);
                        if (errors.Count == 0)
                        {
                            foreach (var item in req.BatchDeclare.Values)
                            {
                                successOrders.AddRange(item.Select(x => x.DetailId));

                            }
                        }
                        else
                        {
                            foreach (var item in req.BatchDeclare.Values)
                            {
                                //某些渠道预报的键不是TracckingNumber，是BoxNumber
                                bool boxNumberIsKey = errors.All(i => string.IsNullOrWhiteSpace(i.TrackingNumber) && !string.IsNullOrWhiteSpace(i.BoxNumber));
                                //派送翼 ACI会以提单来预报
                                bool ladingBillNumberIsKey = errors.All(i => string.IsNullOrWhiteSpace(i.TrackingNumber) && string.IsNullOrWhiteSpace(i.BoxNumber) && !string.IsNullOrWhiteSpace(i.LadingBillNumber));

                                successOrders.AddRange(item.Where(x => !errors.Any(y => (y.TrackingNumber == x.TrackingNumber
                                || (boxNumberIsKey && (y.BoxNumber == x.BoxNumber))
                                  || (ladingBillNumberIsKey && (y.LadingBillNumber == x.LadingBillNumber))
                                ))).Select(x => x.DetailId));

                                if (boxNumberIsKey)
                                {
                                    errorOrders.AddRange(errors.Join(item, x => x.BoxNumber, y => y.BoxNumber, (x, y) => y != null ? new tempBagDeclareDto
                                    {
                                        DetailId = y.DetailId,
                                        ErrorMessage = x.ErrorMessage,
                                        IsSuccess = false,
                                        TrackingNumber = y.TrackingNumber,
                                        LoaddingNumber = y.LadingBillNumber
                                    } : null));
                                }
                                else if (ladingBillNumberIsKey)
                                {
                                    errorOrders.AddRange(errors.Join(item, x => x.LadingBillNumber, y => y.LadingBillNumber, (x, y) => y != null ? new tempBagDeclareDto
                                    {
                                        DetailId = y.DetailId,
                                        ErrorMessage = x.ErrorMessage,
                                        IsSuccess = false,
                                        TrackingNumber = y.TrackingNumber,
                                        LoaddingNumber = y.LadingBillNumber
                                    } : null));
                                }
                                else
                                {
                                    errorOrders.AddRange(errors.Join(item, x => x.TrackingNumber, y => y.TrackingNumber, (x, y) => y != null ? new tempBagDeclareDto
                                    {
                                        DetailId = y.DetailId,
                                        ErrorMessage = x.ErrorMessage,
                                        IsSuccess = false,
                                        TrackingNumber = y.TrackingNumber,
                                        LoaddingNumber = y.LadingBillNumber
                                    } : null));
                                }
                            }
                        }
                        if (successOrders != null && successOrders.Count > 0)
                        {
                            for (var i = 0; i < Math.Ceiling(successOrders.Count / 2000.0); i++)
                            {
                                //每次更新两千条
                                string sql1 = $@"update Logistics_BoxDetail set IsConfim = 1,Message=null where Id in @Id";
                                await _unitOfWork.ExecuteAsync(sql1, new { id = successOrders.Skip(i * 2000).Take(2000).ToList() });
                            }
                        }
                        if (errorOrders != null && errorOrders.Count > 0)
                        {
                            //保存前通知一次相关操作人员
                            try
                            {
                                QYWXWebHook webHook = new QYWXWebHook("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=5eb4675a-773a-40a0-9bad-745501122580");
                                errorOrders.GroupBy(x => x.LoaddingNumber).ToList().ForEach(y =>
                                {
                                    webHook.SendMarkdown(
                                        $"大包预报失败,提单:{y.Key},失败了{y.Count()}条", $"前10条信息如下\n> {string.Join("\n> ", y.Take(10).Select(x => x.TrackingNumber + ":" + x.ErrorMessage))}\n 请立即联系技术人员处理，或在**大包申报日志**中尝试重新提交",
                                        new string[] { "fanlihang" 
                                        , "ZhangCong", "jie", "YanXiaoYan", "HeHuiQun", "hailey", "Mai" 
                                        });
                                });
                            }
                            catch
                            {

                            }
                            string sql2 = @"IF EXISTS(select * from tempdb..sysobjects where id=object_id('tempdb..#tempBagDeclare'))
                                                BEGIN
                                                    DROP TABLE #tempBagDeclare
                                                END
                                            create  table #tempBagDeclare(DetailId int, ErrorMessage nvarchar(max),IsSuccess bit)
                                            ";
                            await _orderRepository.ExecuteSqlAsync(sql2);
                            var errors2 = errorOrders.Select(x => new tempBagDeclare
                            {
                                DetailId = x.DetailId,
                                ErrorMessage = x.ErrorMessage,
                                IsSuccess = x.IsSuccess
                            }).ToList();
                            await _unitOfWork.BulkToDBAsync<tempBagDeclare>(errors2);
                            string sql3 =
                                @"update a  set IsConfim = 1,Message=b.ErrorMessage from  Logistics_BoxDetail(nolock)a join #tempBagDeclare b on a.Id=b.DetailId";
                            await _unitOfWork.ExecuteAsync(sql3);

                        }
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }



        public class tempBagDeclareDto : tempBagDeclare
        {

            public string TrackingNumber
            {
                get; set;
            }

            public string LoaddingNumber
            {
                get; set;
            }
        }

        /// <summary>
        /// 预报类
        /// </summary>
        [Table("#tempBagDeclare")]
        public class tempBagDeclare
        {

            public tempBagDeclare()
            {
                this.IsSuccess = true;
            }

            public bool IsSuccess
            {
                get; set;
            }
            public int DetailId
            {
                get; set;
            }

            public string ErrorMessage
            {
                get; set;
            }
        }

        [NonTrans]
        public async Task OrderConfim(int qty)
        {
            List<int> successOrders = new List<int>(), errorOrders = new List<int>();
            var list = await _orderRepository.GetWaitConfimOrders(qty);
            if (list.Count > 0)
            {
                var groups = list.GroupBy(x => new { x.ServiceCode, x.ChannelId });
                foreach (var g in groups)
                {
                    var baseApi = _baseApis.Where(x => x.ServiceName == g.Key.ServiceCode).FirstOrDefault();
                    var channelApi = (await _channelRepository.QueryAsync(x => x.Id == g.Key.ChannelId)).First();
                    var errors = await baseApi.Confims(g.ToList(), channelApi);
                    if (errors.Count == 0)
                    {
                        successOrders.AddRange(g.Select(x => x.BoxDetailId).ToList());
                    }
                    else
                    {
                        errorOrders.AddRange(g.Where(x => errors.Any(y => y == x.OrderNo || y == x.TrackingNumber))
                            .Select(x => x.BoxDetailId).ToArray());
                        successOrders.AddRange(g.Where(x => !errors.Any(y => y == x.OrderNo || y == x.TrackingNumber))
                            .Select(x => x.BoxDetailId).ToArray());
                    }
                }
                if (successOrders != null && successOrders.Count > 0)
                {
                    string sql1 = $@"update Logistics_BoxDetail set IsConfim = 1,Message=null where Id in @Id";
                    await _orderRepository.ExecuteSqlAsync(sql1, new { id = successOrders });
                }
                if (errorOrders != null && errorOrders.Count > 0)
                {
                    string sql2 = $@"update Logistics_BoxDetail set IsConfim = 1,Message='下单失败' where Id in @Id";
                    await _orderRepository.ExecuteSqlAsync(sql2, new { id = errorOrders });
                }
            }

        }

        public async Task ZZESBUpdateData()
        {

        }

        public async Task ImportPPXFba(System.IO.Stream stream)
        {
            List<ImportPPXFbaModel> models = new List<ImportPPXFbaModel>();
            try
            {
                models = _excelHelper.LoadDataAsStream<ImportPPXFbaModelMapping, ImportPPXFbaModel>(stream);

                BatchCreatePpxFbaOrder(models);
            }
            catch (Exception ex)
            {
                _logger.LogError("导入IB-FBA订单信息失败" + ex.Message);
                throw;
            }
        }

        private async Task BatchCreatePpxFbaOrder(List<ImportPPXFbaModel> models)
        {
            var transferNumbers = models.Select(o => o.TransferNumber);
            var allOrders = await _orderRepository.QueryAsync(o => transferNumbers.Contains(o.TransferNumber));
            var allOrderIds = allOrders.Select(o => o.Id);
            var channel = await _channelRepository.GetAsync(310);
            var allGoods = await _orderGoodsRepository.QueryAsync(g => g.OrderId.In(allOrderIds));

            foreach (var g in allGoods)
            {
                var order = allOrders.FirstOrDefault(o => o.Id == g.OrderId);
                var model = models.FirstOrDefault(m => m.TransferNumber == order.TransferNumber);
                g.Remark = $"{order.TransferNumber}:{model.Length}:{model.Width}:{model.Height}:{model.Weight}";
            }

            var baseApi = _baseApis.FirstOrDefault(a => a.ServiceName == "PPX-FBA");
            var groups = allOrders.GroupBy(o => new { ReceiverName = o.ReceiverName, ReceiverPhone = o.ReceiverPhone, ReceiverZipCode = o.ReceiverZipCode, ReceiverStreet = o.ReceiverStreet, ReceiverCity = o.ReceiverCity, ReceiverState = o.ReceiverState, ReceiverCountryCode = o.ReceiverCountryCode });

            foreach (var g in groups)
            {
                Order_Order masterOrder = g.First();
                var groupOrderIds = g.Select(o => o.Id);
                var groupNumbers = g.Select(o => o.TransferNumber);
                var groupOrderModels = models.Where(m => groupNumbers.Contains(m.TransferNumber));
                var groupOrderGoods = allGoods.Where(g => groupOrderIds.Contains(g.OrderId)).ToList();
                var groupModes = models.Where(m => groupNumbers.Contains(m.TransferNumber));


                //多箱并且重量不超过21KG，则一票多箱
                if (g.Count() > 1 && groupModes.Sum(m => m.Weight) > 21m)
                {
                    var uploadResult = await baseApi.DataUpload(masterOrder, groupOrderGoods, channel, null);
                    if (uploadResult.IsSuccess == true)
                    {
                        var pdfContent = await baseApi.DrawPdfLabel(uploadResult, channel, masterOrder, groupOrderGoods);
                    }
                }
                else
                {
                    foreach (var order in g)
                    {
                        var orderGoods = allGoods.Where(g => g.OrderId == order.Id)?.ToList();
                        var uploadResult = await baseApi.DataUpload(order, orderGoods, channel, null);
                        if (uploadResult.IsSuccess == true)
                        {
                            var pdfContent = await baseApi.DrawPdfLabel(uploadResult, channel, order, orderGoods);
                        }
                    }
                }


            }
        }

        private void UpdateFbaOrderTrackingNumber(string packTrackingNumberInfos)
        {

        }

        public async Task THInputOrder(System.IO.Stream stream)
        {
            List<OPTHOrderModel> models = new List<OPTHOrderModel>();
            try
            {
                models = _excelHelper.LoadDataAsStream<OPTHOrderMapping, OPTHOrderModel>(stream);
                models = models.Where(x => x.ChannelName == "逸达泰国COD头程专线").ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError("导入订单信息失败" + ex.Message);
                throw ex;
            }

            List<OrderInputDto> orderInputDtos = new List<OrderInputDto>();


            foreach (var model in models)
            {
                int systemId = await _orderRepository.GetNewId();
                string orderNo = $"XYYEX" + systemId.ToString("0000000000") + "YQ";
                OrderInputDto order = new OrderInputDto
                {
                    UserBoxNumber = model.UserBoxNumber,
                    ChannelId = 159,
                    CreateOrderChannelId = 159,
                    CustomerId = 1,
                    CustomerOrderNo = "OP" + model.CustomerOrderNo,
                    TrackingNumber = model.TrackingNumber,
                    ReceiverState = model.ReceiverState,
                    ReceiverCity = model.ReceiverCity,
                    ReceiverZipCode = model.ReceiverZipCode,
                    ReceiverName = model.ReceiverName,
                    ReceiverPhone = model.ReceiverPhone,
                    ReceiverStreet = model.ReceiverStreet,
                    CustomerWeight = 100,
                    ForwardingSystemId = 1,
                    CreateTime = DateTime.Now,
                    UnusualReason = UnusualReasonType.无,
                    OrderStatus = 1,
                    OrderTime = DateTime.Now,
                    ERPApiId = 2,
                    ReceiverCountryCode = "TH",
                    RemoteState = RemoteState.无,
                    SourceType = 2,
                    ReissueStatus = ReissueStatus.无,
                    SystemNo = orderNo,
                    TransferNumber = orderNo,
                    SenderName = "",
                    SenderCity = "",
                    SenderCompany = "",
                    SenderCountryCode = "",
                    SenderCountryName = "",
                    SenderEmail = "",
                    SenderPhone = "",
                    SenderState = "",
                    SenderStreet = "",
                    SenderZipCode = "",
                    GoodsList = new List<Order_OrderGoods>()
                };
                order.GoodsList.Add(new Order_OrderGoods
                {
                    CnName = model.CnName,
                    EnName = model.EnName,
                    DeclareCurrency = "USD",
                    DeclareFee = 1,
                    HsCode = string.Empty,
                    Quantity = model.Quantity,
                    CreateTime = DateTime.Now,
                    GoodsNumber = string.Empty
                });
                orderInputDtos.Add(order);
            }


            //箱子列表
            var BoxNumbers = orderInputDtos.Where(x => !string.IsNullOrEmpty(x.UserBoxNumber)).GroupBy(x => x.UserBoxNumber).ToList();
            foreach (var boxNumber in BoxNumbers)
            {
                Logistics_Box box = new Logistics_Box
                {
                    BoxNumber = GenerateBoxNumber(),
                    UserBoxNumber = boxNumber.Key,
                    ChannelId = 159,
                    CanElectricGoosd = false,
                    CanSpecialGoods = false,
                    CreateTime = DateTime.Now,
                    CustomerId = 1,
                    ParcelQty = boxNumber.Count()
                };
                int boxId = (int)await _boxRepository.InsertAsync(box);
                foreach (var item in boxNumber)
                {
                    item.UserBoxNumber = box.BoxNumber;
                    item.BoxId = boxId;
                }
            }
            await _orderRepository.InputOrderAndGoods(orderInputDtos);
        }

        public async Task<IEnumerable<SysWarehouseFileLog>> GetWaitDownFile(int qty = 200)
        {
            return await _orderRepository.GetWaitDownFile(qty);
        }

        public async Task UpdateDownFile(List<SysWarehouseFileLog> transfernums)
        {
            await _orderRepository.UpdateDownFile(transfernums);
        }

        public async Task<PageResult<View_QueryOverCancelOrders>> QueryOverCancelOrders(QueryModel queryModel)
        {
            return await QueryOverCancelOrders(queryModel);
        }

        public async Task CustomerConfim(int qty)
        {
            string sql = $@"select top  100 b.TrackingNumber,b.OPWeight,c.DeliveryTime from logistics_boxdetail(nolock) a
	                                join order_order(nolock)b on a.orderId=b.Id
	                                join Logistics_Box(nolock)c on c.id=a.BoxId
	                                where a.CustomerConfimStatus is null and b.CustomerId = 306
            ";
            var list = await _orderRepository.QueryCustomerData(sql);
            FrPostApi postApi = new FrPostApi();
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var item in list)
            {
                string result = postApi.Out(item.TrackingNumber, item.OPWeight, item.DeliveryTime);
                stringBuilder.AppendLine($"Update Logistics_BoxDetail set CustomerConfimStatus='{result}' where TrackingNumber ='{item.TrackingNumber}'");
            }
            if (stringBuilder.Length > 0)
                await _orderRepository.ExecuteSqlAsync(stringBuilder.ToString());
        }

        public async Task<bool> AsyncServiceTrackingNumber(int qty)
        {
            string sql = @$"select top {qty} SourceType,CustomerOrderNo,ERPApiId,Id,ServicesOrderNo,SystemNo,TrackingNumber,ChannelId,datediff(HOUR,ReceiveTime,getdate()) from Order_Order(nolock) 
                                where WaitSysncServiceTrackingNumber=1 and orderStatus<>4 and OrderStatus>=2 and datediff(HOUR,UpdateTime,getdate())>2  and ReceiveTime>'2022-05-05' and datediff(HOUR,ReceiveTime,getdate())>4  and datediff(day,ReceiveTime,getdate())<24";
            //string sql = @$"select top {qty} SourceType,CustomerOrderNo,ERPApiId,Id,ServicesOrderNo,SystemNo,TrackingNumber,ChannelId,datediff(HOUR,ReceiveTime,getdate()) from Order_Order(nolock) 
            //                    where WaitSysncServiceTrackingNumber=1 and orderStatus<>4 and OrderStatus>=2 and datediff(HOUR,UpdateTime,getdate())>2  and ReceiveTime>'2022-05-05' and datediff(HOUR,ReceiveTime,getdate())>4  and datediff(day,ReceiveTime,getdate())<24";
            //string sql = @"select * from order_order where SystemNo = 'XYYEX028548150YQ'";

            var data = await _orderRepository.QueryBySqlAsync(sql);
            List<Task> tasks = new List<Task>();
            foreach (var item in data.GroupBy(x => x.ChannelId))
            {
                var channel = await _channelRepository.GetAsync(item.Key);
                if (channel == null)
                {
                    throw new Exception("未找到相关渠道");
                }
                else
                {
                    var api = _baseApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
                    foreach (var o in item)
                    {
                        string TrackingNumber = "";
                        try
                        {
                            TrackingNumber = await api.GetTrackingNumber(o.SystemNo, o.TrackingNumber, o.ServicesOrderNo, channel);
                        }
                        catch (Exception ex)
                        {
                            //出错时，不关心具体错误。 
                            string updateOrderSql = $@"update Order_Order set UpdateTime=getdate() where Id={o.Id}";
                            await _channelRepository.ExecuteSqlAsync(updateOrderSql);
                            continue;
                        }


                        if (string.IsNullOrEmpty(TrackingNumber) || (!TrackingNumber.StartsWith("420") && !TrackingNumber.StartsWith("")))
                        {
                            //出错时，不关心具体错误。 
                            string updateOrderSql = $@"update Order_Order set UpdateTime=getdate() where Id={o.Id}";
                            await _channelRepository.ExecuteSqlAsync(updateOrderSql);
                            continue;
                        }
                        string updateSql = $@"update Logistics_BoxDetail set TrackingNumber='{TrackingNumber}' where OrderId={o.Id}";
                        await _channelRepository.ExecuteSqlAsync(updateSql);

                        await _orderRepository.UpdateByConditionAsync(x => x.Id == o.Id, new
                        {
                            TrackingNumber = TrackingNumber,
                            WaitSysncServiceTrackingNumber = false
                        });

                        if (o.SourceType == 4 && o.ERPApiId > 0)
                        {
                            if (o.CustomerId != 252 && o.CustomerId != 221 && !o.IsOnline && o.CustomerId != 281 && o.CustomerId != 287 && o.CustomerId != 481)
                            {
                                await _jobMessageRepository.InsertAsync(new Job_Message
                                {
                                    Action = "/API/LoadOrder/UpdateExpressNo?ApiId=" + o.ERPApiId,
                                    JsonMessage = Newtonsoft.Json.JsonConvert.SerializeObject(new
                                    {
                                        CustomerOrderNo = o.CustomerOrderNo,
                                        TrackingNumber = TrackingNumber
                                    })
                                });
                            }
                        }

                        await _alterExpressNoLogRepository.InsertAsync(new AlterExpressNoLog
                        {
                            OrderId = o.Id,
                            NewChannelId = o.ChannelId,
                            NewLabelPath = o.ServiceLabelPath,
                            OldChannelid = o.ChannelId,
                            NewTrackingNumber = TrackingNumber,
                            OldTrackingNumber = o.SystemNo,
                            OldLabelPath = o.ServiceLabelPath
                        });
                    }

                }
            }
            return data.Count() == 0;
        }


        public async Task<List<BagDeclareErrosResult>> GetBagDeclareError(string laddingBillNumber, string serviceCode)
        {
            string sql = $@"select a.TrackingNumber,b.Message as ErrorMessage from Order_Order(nolock)a
                                        join Logistics_BoxDetail(nolock)b on a.id = b.OrderId
                              join Logistics_Box(nolock)c on c.id = b.BoxId
                              join Logistics_Channel(nolock)d on d.Id = a.ChannelId
                              where c.LadingBillNumber = '{laddingBillNumber}' and b.IsConfim = 1 and Message is not null  and d.ServiceChannelCode = '{serviceCode}'";
            return (await _unitOfWork.QueryBySqlAsync<BagDeclareErrosResult>(sql)).ToList();
        }

        public async Task<List<string>> GetPackingOrderId(List<string> SystemNos)
        {
            var xml = string.Join("\r\n", SystemNos.Select(x => $"<NumberList><Number>{x}</Number></NumberList>"));
            string sql = @"
if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..#temp_searchs') and type='U')
    drop table #temp_search

DECLARE @idoc int
                                            DECLARE @doc varchar(max)
                                            SET @doc ='
                                            <ROOT>
                                            {0}
                                            </ROOT>'
                                            --Create an internal representation of the XML document.
                                            EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
                                            -- SELECT stmt using OPENXML rowset provider
                                            SELECT * into #temp_searchs
                                            FROM   OPENXML (@idoc, '/ROOT/NumberList',2)
                                                     WITH (Number nvarchar(64)) ";
            string excuteSql = string.Format(sql, xml) + "select a.SystemNo from Order_Order(nolock) a where a.OrderStatus>=3 and a.OrderStatus!=4 and (a.SystemNo in(select Number from #temp_searchs) or a.TrackingNumber in (select Number from #temp_searchs) or a.TransferNumber in (select Number from #temp_searchs) ) ";
            return (await _orderRepository.QueryAsync<string>(excuteSql)).ToList();
        }

        public async Task ReBagDeclare(string laddingBillNumber, string serviceCode)
        {
            string sql = $@"
                            update b set b.IsConfim=0 from Order_Order(nolock)a join Logistics_BoxDetail(nolock)b on a.id=b.OrderId
                             join Logistics_Box(nolock)c on c.id=b.BoxId
                             join Logistics_Channel(nolock)d on d.Id=a.ChannelId
                             where c.LadingBillNumber='{laddingBillNumber}' and b.IsConfim =1 and d.ServiceChannelCode='{serviceCode}'";
            await _unitOfWork.ExecuteAsync(sql);
        }

        public async Task<List<IBBagLabbelResult>> GetIBBagLabel(List<int> boxIds)
        {
            List<IBBagLabbelResult> result = new List<IBBagLabbelResult>();
            var boxs = await _boxRepository.QueryAsync(b => b.Id.In(boxIds));
            if (boxs?.Any() != true)
            {
                throw new Exception("找不到箱子");
            }
            foreach (var id in boxIds)
            {
                if (!boxs.Any(b => b.Id == id))
                {
                    throw new Exception($"找不到箱子,ID:{id}");
                }
            }

            var allBoxIds = boxs.Select(b => b.Id);
            var allBoxDetails = await _BoxDetailRepository.QueryAsync(d => d.BoxId.In(allBoxIds));
            var allOrderIds = allBoxDetails.Select(d => d.OrderId);

            int pageLength = 1500;
            int pageCount = (int)Math.Ceiling(allOrderIds.Count() / (decimal)pageLength);

            List<Order_Order> allOrders = new List<Order_Order>();
            for (int p = 0; p < pageCount; p++)
            {
                var pageOrderIds = allOrderIds.Skip(p * pageLength).Take(pageLength);
                var pageOrders = await _orderRepository.QueryAsync(o => o.Id.In(pageOrderIds));
                allOrders.AddRange(pageOrders);
            }

            var allChannelIds = boxs.Select(b => b.ChannelId).Distinct();
            var allChannels = await _channelRepository.QueryAsync(c => c.Id.In(allChannelIds));

            //List<string> result = new List<string>();
            List<Logistics_IBBagLabel> bagLabels = new List<Logistics_IBBagLabel>();

            foreach (var box in boxs)
            {
                var channel = allChannels.First(c => c.Id == box.ChannelId);
                var boxDetails = allBoxDetails.Where(d => d.BoxId == box.Id);
                var boxDetailOrderIds = boxDetails.Select(d => d.OrderId);
                var orders = allOrders.Where(o => boxDetailOrderIds.Contains(o.Id));
                ChannelBagLabelParam param = new ChannelBagLabelParam
                {
                    Box = box,
                    BoxDetails = boxDetails,
                    Channel = channel,
                    Orders = orders
                };

                var baseApi = _packLabelApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
                if (baseApi == null)
                {
                    throw new Exception("渠道API没有实现IUItidelApi");
                }
                try
                {


                    var resultData = await baseApi.GetChannelBagLabel(param);
                    var r = new IBBagLabbelResult { LabelContent = resultData.Label, Success = true };
                    result.Add(r);

                    Logistics_IBBagLabel bagLabel = new Logistics_IBBagLabel
                    {
                        BoxId = box.Id,
                        BoxNumber = box.BoxNumber,
                        LabelContent = resultData.Label,
                        CreateTime = DateTime.Now,
                        CreateUserName = "admin",
                        ChannelBagNumber = resultData.ChannelBagNumber,
                        DestinationPortCode = resultData.DestinationPortCode,
                        DestinationTurnOverCode = resultData.DestinationTurnOverCode,
                        ServiceCode = resultData.ServiceCode
                    };
                    await _boxRepository.UpdateByPrimaryKeyAsync(box.Id, "UserBoxNumber", resultData.ChannelBagNumber);
                    bagLabels.Add(bagLabel);
                }
                catch (Exception ex)
                {
                    Logistics_IBBagLabel bagLabel = new Logistics_IBBagLabel
                    {
                        BoxId = box.Id,
                        BoxNumber = box.BoxNumber,
                        LabelContent = string.Empty,
                        CreateTime = DateTime.Now,
                        CreateUserName = "admin",
                        Message = ex.Message,
                    };
                    bagLabels.Add(bagLabel);

                    var r = new IBBagLabbelResult { Success = false, Message = ex.Message };
                    result.Add(r);
                }
            }
            if (bagLabels?.Any() == true)
            {
                await _IBBagLabelRepository.BulkToDBAsync(bagLabels);
            }
            return result;
        }

        public async Task CancelIBBagLabel(List<int> boxIds)
        {
            var boxs = await _boxRepository.QueryAsync(b => b.Id.In(boxIds));
            if (boxs?.Any() != true)
            {
                throw new Exception("找不到箱子");
            }
            var boxNumbers = boxs.Select(b => b.BoxNumber);
            var channelIds = boxs.Select(b => b.ChannelId);
            var allChannels = await _channelRepository.QueryAsync(c => c.Id.In(channelIds));
            foreach (var box in boxs)
            {
                var boxNumber = box.BoxNumber;
                var channel = allChannels.First(c => c.Id == box.ChannelId);

                CannelIBBagParam param = new CannelIBBagParam
                {
                    BoxNumber = boxNumber,
                    Channel = channel
                };

                var baseApi = _packLabelApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
                if (baseApi == null)
                {
                    throw new Exception("渠道API没有实现IUItidelApi");
                }
                await baseApi.CannelBag(param);
            }
        }
        #region 订单管理
        public async Task<PageResult<CustomerOrder>> GetOrderPager(QueryModel queryModel)
        {
            PageResult<CustomerOrder> result = new PageResult<CustomerOrder>();
            var status = queryModel.QueryParamer.FirstOrDefault(x => x.Filed == "OrderStatus");
            if (status != null && status.Value == "10000")
            {
                ///取上传时失败、待处理的草稿订单
                result = await _orderRepository.GetCustomerDraftOrderList(queryModel);
                SetStatus(result.Result);
            }
            else
            {
                //取成功订单
                result = await _orderRepository.GetCustomerOrderPager(queryModel);
                SetStatus(result.Result);
            }
            //tags数据处理
            var tags = await _moreThanOneTicketService.GetMpsOrders(result.Result.Select(x => x.MpsOrderId));
            //商品数量处理
            var orderQuantitys = await _moreThanOneTicketService.GetMpsBoxCount(result.Result.Select(x => x.Id));
            var customers = await _customerService.CacheGetAllCustomers();
            var channels = await _channelService.CacheGetAllChannel();
            result.Result.ToList().ForEach(order =>
            {
                order.ChannelName = channels.FirstOrDefault(x => x.Id == order.ChannelId)?.PublicName;
                order.CreateOrderChannelName = channels.FirstOrDefault(x => x.Id == order.CreateOrderChannelId)?.PublicName;
                order.CustomerNumber = customers.FirstOrDefault(x => x.Id == order.CustomerId)?.CustomerNumber;
                order.Quantity = orderQuantitys?.Where(x => x.OrderId == order.Id)?.FirstOrDefault()?.Quantity ?? 0;
                var customer = customers.Where(x => x.Id == order.CustomerId).FirstOrDefault();
                if (customer != null)
                {
                    order.CustomerName = customer.CompanyName;
                }
                if (tags != null) { var tempTag = tags.Where(x => x.Id == order.MpsOrderId)?.FirstOrDefault()?.Tags; order.Tags = string.IsNullOrEmpty(tempTag) ? null : tempTag.Split(";").ToList(); }
                if (tags != null)
                {
                    var tempTag = tags.Where(x => x.Id == order.MpsOrderId)?.FirstOrDefault();
                    if (tempTag != null && tempTag.Magnetic) { order.attrs.Add("带磁"); }
                    if (tempTag != null && tempTag.Electric) { order.attrs.Add("带电"); }
                    if (tempTag != null && tempTag.Liquid) { order.attrs.Add("危险品"); }
                }
            });
            return result;
        }
        public async Task<List<OrderQtys>> GetOrderQty(QueryModel qm)
        {
            var qm2 = qm.Copy<QueryModel>();
            qm2.QueryParamer = qm.QueryParamer.CopyList<QueryParamer>().ToList();
            var doqt = await _orderRepository.GetCustomerDraftOrderCount(qm2);
            var all = await _orderRepository.GetOrderQty(qm);
            all.Add(doqt);
            return all;
        }
        public async Task<CustomerOrder> Get(int id)
        {
            var order = await _orderRepository.GetCustomerOrder(id);
            if (order.MpsOrderId > 0) { order.UploadFileUrl = (await _moreThanOneTicketService.Get(id, 0))?.UploadFileUrl; }
            SetStatus(new List<CustomerOrder> { order });
            var dto1 = GetTrackingLogs(new string[] { order.TrackingNumber }, "logistics_tracking", "trackingGroup");
            var dto2 = GetTrackingLogs(new string[] { order.TrackingNumber }, "logistics_frist", "frist");
            var dto3 = GetTrackingLogs(new string[] { order.TrackingNumber }, "logistics_supplement", "supplement");
            order.HasIOSS = !string.IsNullOrEmpty(order.ioss);
            order.TrackingLogs = new List<Logistics_TrackingLog>(order.FristTrackingLogs);
            order.TrackingLogs.AddRange(dto1);
            order.TrackingLogs.AddRange(dto2);
            order.TrackingLogs.AddRange(dto3);
            order.TrackingLogs = order.TrackingLogs.OrderBy(x => x.TriggerTime).ToList();
            order.SignDay = order.ReceiveTime.HasValue && order.LatestLogisticsStatus == "Delivered"
            ? (int)((order.LastGetTime - order.ReceiveTime).Value.TotalDays) : null;
            return order;
        }
        private static void SetStatus(IEnumerable<CustomerOrder> orders)
        {
            foreach (var item in orders)
            {
                if (item.LatestLogisticsStatus == "notfound" || item.LatestLogisticsStatus == "transit" || item.LatestLogisticsStatus == "noUpdate" || string.IsNullOrEmpty(item.LatestLogisticsStatus))
                {
                    item.LatestLogisticsStatus = "Transit";
                }
                if (item.LatestLogisticsStatus == "delivered")
                {
                    item.LatestLogisticsStatus = "Delivered";
                }
                if (item.LatestLogisticsStatus == "exception")
                {
                    item.LatestLogisticsStatus = "Exception";
                }
                if (item.LatestLogisticsStatus == "undelivered")
                {
                    item.LatestLogisticsStatus = "UnDelivered";
                }
                if (item.LatestLogisticsStatus == "pickup")
                {
                    item.LatestLogisticsStatus = "Pickup";
                }
                if (string.IsNullOrEmpty(item.TransferNumber))
                {
                    item.LatestLogisticsStatus = "NotFound";
                }

            }
        }
        public List<Logistics_TrackingLog> GetTrackingLogs(string[] trackingNumber, string index, string type)
        {
            List<Logistics_TrackingLog> dto = new List<Logistics_TrackingLog>();
            ESRequest eSRequest = new ESRequest("http://120.24.149.148:9526", index, type, "mget");
            string strData = eSRequest.ExecuteQeury("{\"ids\":[" + string.Join(",", trackingNumber.Select(x => "\"" + x + "\"")) + "]}");
            var data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(strData);
            foreach (var item in data.docs)
            {
                bool.TryParse(item.found?.ToString(), out bool found);
                if (found)
                {
                    foreach (var log in item._source.list)
                    {
                        dto.Add(new Logistics_TrackingLog
                        {
                            StatusString = log.statusString.Value as string,
                            TriggerTime = (DateTime)log.triggerTime.Value,
                            Status = (int)log.status.Value,
                            TransferNumber = item._source.trackingNumber.Value,
                            Location = log.location?.Value ?? ""
                        });
                    }
                }
            }
            return dto;
        }
        public async Task<CustomerOrder> GetCustomerDraftOrder(int id)
        {
            var order = await _orderRepository.GetCustomerDraftOrder(id);
            return order;
        }
        public async Task<List<CustomerOrder>> GetCustomerOrderList(QueryModel queryModel)
        {
            var status = queryModel.QueryParamer.FirstOrDefault(x => x.Filed == "OrderStatus");
            if (status != null && status.Value == "10000")
            {
                throw new Exception("草稿订单不支持导出");
            }
            else
            {
                //取成功订单
                var list = await _orderRepository.GetCustomerOrderList(queryModel);
                SetStatus(list);
                return list;
            }
        }

        public async Task<List<Order_OrderGoods>> GetGoods(int orderId)
        {
            var goods = await _orderGoodsRepository.QueryAsync(x => x.OrderId == orderId);
            return goods.ToList();
        }

        public async Task UpdateLastInfo(Order_Order order)
        {
            if (order == null)
                throw new Exception("更新订单末端派送信息失败，未传入订单参数");
            if (order.Id == 0)
                throw new Exception("更新订单末端派送信息失败，订单Id未传入");
            else
            {
                int qty =
                    await _orderRepository.ExecuteSqlAsync("update Order_Order Set TrackingNumber = @TrackingNumber," +
                    "ServiceLabelPath=@ServiceLabelPath,ServiceLabelUrl=@ServiceLabelUrl,ChannelId=@ChannelId where Id=@Id ",
                    new
                    {
                        Id = order.Id,
                        ServiceLabelPath = order.ServiceLabelPath,
                        ServiceLabelUrl = order.ServiceLabelUrl,
                        TrackingNumber = order.TrackingNumber,
                        ChannelId = order.ChannelId
                    });
                if (qty <= 0)
                    throw new Exception($"更新订单末端派送信息失败，更新数据订单{order.Id}失败");
            }

        }

        public async Task<List<string>> ConfimChannelOrders(List<string> numbers, string serviceCode)
        {
            var baseApi = _baseApis.Where(x => x.ServiceName == serviceCode).FirstOrDefault();
            var channel = (await _channelRepository.QueryAsync(x => x.ServiceCode == serviceCode)).First();

            if (baseApi != null && channel != null)
            {
                List<OrderConfimRequest> orders = numbers.Select(i => new OrderConfimRequest { TrackingNumber = i }).ToList();
                var errorOrders = await baseApi.Confims(orders, channel);
                return errorOrders;
            }
            return new List<string>();
        }

        public async Task ConfimChannelOrdersByBox(List<int> boxIds)
        {
            IEnumerable<OrderConfimRequest> orders = await _boxRepository.GetBoxOrderConfirmItems(boxIds);
            var channelOrderGroups = orders.GroupBy(i => i.ChannelId);
            var channelIds = channelOrderGroups.Select(g => g.Key);
            var channels = await _channelRepository.QueryAsync(c => c.Id.In(channelIds));

            foreach (var group in channelOrderGroups)
            {
                var channel = channels.FirstOrDefault(c => c.Id == group.Key);
                //channel = (await _channelRepository.QueryAsync(c => c.Id == 500)).FirstOrDefault();
                var baseApi = _baseApis.Where(x => x.ServiceName == channel.ServiceCode).FirstOrDefault();
                var items = group.ToList();
                var errorOrders = await baseApi.Confims(items, channel);

                var successList = group.Where(i => !errorOrders.Any(e => e == i.TrackingNumber));
                await UpdateOrderConfirmed(successList);
            }
        }

        private async Task<bool> UpdateOrderConfirmed(IEnumerable<OrderConfimRequest> allSuccessResult)
        {
            if (allSuccessResult?.Any() != true)
                return false;

            IEnumerable<int> boxDetailIds = allSuccessResult.Select(i => i.BoxDetailId);
            var count = await _BoxDetailRepository.SetConfirmStatus(boxDetailIds);
            return count > 0;
        }


        #endregion
    }

    public class OPTHOrderModel : Order_Order
    {
        public string UserBoxNumber { get; set; }
        public string ChannelName { get; set; }

        /// <summary>
        /// 订单编号
        /// </summary>
        public int OrderId { get; set; }
        /// <summary>
        /// 商品编码
        /// </summary>
        public string GoodsNumber { get; set; }
        /// <summary>
        /// 商品中文描述
        /// </summary>
        public string CnName { get; set; }
        /// <summary>
        /// 商品英文描述
        /// </summary>
        public string EnName { get; set; }
        /// <summary>
        /// 海关编码
        /// </summary>
        public string HsCode { get; set; }
        /// <summary>
        /// 申报币种
        /// </summary>
        public string DeclareCurrency { get; set; }
        /// <summary>
        /// 申报单价
        /// </summary>
        public decimal DeclareFee { get; set; }
        /// <summary>
        /// 申报数量
        /// </summary>
        public int Quantity { get; set; }
        /// <summary>
        /// 申报材质
        /// </summary>
        public string Material { get; set; }
        /// <summary>
        /// 申报单位
        /// </summary>
        public string Unit { get; set; }
        /// <summary>
        /// Url地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        ///重量
        /// </summary>
        public int Weight { get; set; }

    }

    public class OPTHOrderMapping : MSExcelClassMapping<OPTHOrderModel>
    {
        public OPTHOrderMapping()
        {
            Map(x => x.UserBoxNumber).Name("PKG号").Name("PKG单号");
            Map(x => x.ChannelName).Name("快递方式").Name("物流渠道名称");
            Map(x => x.CustomerOrderNo).Name("发运包裹单号");
            Map(x => x.TrackingNumber).Name("物流单号");
            Map(x => x.ReceiverState).Name("收件省/州");
            Map(x => x.ReceiverCity).Name("收件城市");
            Map(x => x.ReceiverStreet).Name("收件地址");
            Map(x => x.ReceiverZipCode).Name("收件邮编");
            Map(x => x.ReceiverName).Name("收件人");
            Map(x => x.ReceiverPhone).Name("收件电话");
            Map(x => x.CnName).Name("物品中文名");
            Map(x => x.EnName).Name("物品英文名");
            Map(x => x.Quantity).Name("物品数量");
        }
    }

    public class ImportPPXFbaModel
    {
        public string TransferNumber { get; set; }
        public int Length { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public decimal Weight { get; set; }
    }

    public class ImportPPXFbaModelMapping : MSExcelClassMapping<ImportPPXFbaModel>
    {
        public ImportPPXFbaModelMapping()
        {
            Map(x => x.TransferNumber).Name("XYY单号");
            Map(x => x.Length).Name("长(CM)");
            Map(x => x.Width).Name("宽(CM)");
            Map(x => x.Height).Name("高(CM)");
            Map(x => x.Weight).Name("重量(KG)");
        }
    }
}
