using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.Data.Infrastructure;
using XYY.TaskTrack.Standard;
using Dapper;
using XYY.Model.Standard.Order;
using System.Collections.Concurrent;
using XYY.Service.Standard.ChannelApi.Base;
using XYY.Model.Standard.Channel;
using XYY.Core.Standard;

namespace XYY.Service.Standard.Order
{

    public class AddHNJobMessage
    {
        public string LadingNumber
        {
            get; set;
        }
    }

    public interface IAddHNJobSubscribe : IBaseConsumer<AddHNJobMessage>
    {

    }

    public class AddHNJobSubscribe : BaseConsumer<AddHNJobMessage>, IAddHNJobSubscribe
    {
        private IUnitOfWork _unitOfWork;
        private ILogger<AddHNJobMessage> _jobLogger;

        public AddHNJobSubscribe(IMQManager mq, IUnitOfWork _unitOfWork, ILogger<AddHNJobMessage> jobLogger) : base(mq)
        {
            _jobLogger = jobLogger;
            this._unitOfWork = _unitOfWork;
        }

        public class ZZESBUpdateData : BaseEntity
        {

            public string TrackingNumber
            {
                get; set;
            }

            public string ESBTrackingNumber
            {
                get; set;
            }

            public string Message
            {
                get; set;
            }


            public string Status
            {
                get; set;
            }

            public int OrderId
            {
                get; set;
            }
        }

        public override async Task Consume(AddHNJobMessage job)
        {

            try
            {
                _jobLogger.LogInformation("收到提单请求" + job.LadingNumber);

                string sql = $@"select a.* 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
                                            left join ZZESBUpdateData(nolock) d on d.orderid= a.Id
                                        where c.LadingBillNumber='{job.LadingNumber}' and d.id is null ";
                //首先添加一次当前提单缺少订单的信息

                var orderList = await this._unitOfWork.QueryBySqlAsync<Order_Order>(sql);


                var blist = orderList.Select(x => new ZZESBUpdateData
                {
                    CreateTime = DateTime.Now,
                    CreateUserName = "system",
                    TrackingNumber = x.TrackingNumber,
                    Status = "Wait",
                    OrderId = x.Id
                }).ToList();
                await _unitOfWork.BulkToDBAsync<ZZESBUpdateData>(blist);

                //再次更新错误订单进行重试
                await _unitOfWork.ExecuteAsync($@"update d set d.Status='Wait' 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
                                            left join ZZESBUpdateData(nolock) d on d.orderid = a.Id
                                        where c.LadingBillNumber = '{job.LadingNumber}'  and status='Error'");

                //取数据
                string sqlOrder = $@"select a.* 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
                                            left join ZZESBUpdateData(nolock) d on d.orderid= a.Id
                                        where c.LadingBillNumber='{job.LadingNumber}' and d.Status='Wait' ";

                orderList = await this._unitOfWork.QueryBySqlAsync<Order_Order>(sqlOrder);
                string sqlGoods = $@"select e.* 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 Order_OrderGoods(nolock) e on e.OrderId=a.Id
                                            left join ZZESBUpdateData(nolock) d on d.orderid= a.Id
                                        where c.LadingBillNumber='{job.LadingNumber}' and d.Status='Wait' ";

                var orderGoods = await this._unitOfWork.QueryBySqlAsync<Order_OrderGoods>(sqlGoods);

                var channel = await this._unitOfWork.GetAsync<Logistics_Channel>(227);

                //关闭连接
                if (_unitOfWork.Connection.State == System.Data.ConnectionState.Open)
                    _unitOfWork.Connection.Close();

                //线程数
                int workQty = 10;
                var batchDto = orderList.Select(x => new BathcDto { Order = x, OrderGoods = orderGoods.Where(y => y.OrderId == x.Id).ToList() });
                ConcurrentQueue<BathcDto> dto = new ConcurrentQueue<BathcDto>(batchDto);
                List<Task> tasks = new List<Task>();
                var api = new ChannelApi.HuaLei.Api();
                List<ZZESBUpdateData> results = new List<ZZESBUpdateData>();
                Dictionary<string, string> goodsCorrect = new Dictionary<string, string>();
                goodsCorrect.Add("首饰", "项链");
                goodsCorrect.Add("厨房工具", "酱料瓶");
                goodsCorrect.Add("衣物", "休闲服");
                goodsCorrect.Add("箱包", "女士包包");
                goodsCorrect.Add("塑料", "塑料A");
                goodsCorrect.Add("模型", "模型A");
                goodsCorrect.Add("外套", "夹克A");
                goodsCorrect.Add("服装", "休闲服");
                goodsCorrect.Add("鞋子", "休闲鞋");
                goodsCorrect.Add("工具", "工具A");
                //使用单独一个连接进行更新操作
                using (System.Data.SqlClient.SqlConnection sqlConnection = new System.Data.SqlClient.SqlConnection("Server=rm-wz96o72qd45w3d6mvyo.sqlserver.rds.aliyuncs.com,3433;Pooling=true;Max Pool Size=40000;Min Pool Size=0;initial catalog=xyy_wms;uid=xyy;pwd=SsAGn%SK*Ydjeibw;MultipleActiveResultSets=true;"))
                {
                    sqlConnection.Open();

                    try
                    {

                        for (int i = 0; i < workQty; i++)
                        {
                            tasks.Add(Task.Run(async () =>
                            {
                                while (dto.TryDequeue(out var item))
                                {
                                    //电话修正
                                    if (string.IsNullOrEmpty(item.Order.ReceiverPhone) || item.Order.ReceiverPhone.Length <= 5)
                                    {
                                        item.Order.ReceiverPhone = "123456";
                                    }

                                    foreach (var g in orderGoods)
                                    {
                                        if (goodsCorrect.ContainsKey(g.CnName))
                                        {
                                            g.CnName = goodsCorrect[g.CnName];
                                        }
                                        if (g.HsCode != null && g.HsCode.Length < 10)
                                        {
                                            g.HsCode = g.HsCode.PadRight(10, '0');
                                        }
                                        if (g.EnName.Contains("%"))
                                        {
                                            g.EnName = g.EnName.Replace("%", "％");
                                        }
                                    }

                                    item.Order.CustomerOrderNo = item.Order.TrackingNumber;
                                    item.Order.SystemNo = item.Order.TrackingNumber;
                                    item.Order.CustomerWeight = item.Order.OPWeight;
                                    if (item.Order.OPWeight > 10000)
                                    {
                                        item.Order.CustomerWeight = 10000;
                                    }
                                    try
                                    {
                                        var result = await api.DataUpload(item.Order, item.OrderGoods, channel,new ExtendArg());
                                        //写入记录
                                        await sqlConnection.ExecuteAsync($"update ZZESBUpdateData set Status='OK',ESBTrackingNumber='{result.TrackingNumber}' where OrderId={item.Order.Id}");
                                    }
                                    catch (Exception ex)
                                    {
                                        await sqlConnection.ExecuteAsync($"update ZZESBUpdateData set Status='Error',Message='{ ex.Message}' where OrderId={item.Order.Id}");
                                    }
                                }
                            }));
                        }
                        Task.WaitAll(tasks.ToArray());
                    }
                    catch (Exception ex)
                    {
                        _jobLogger.LogError(ex.Message);
                    }
                    finally
                    {
                        if (sqlConnection.State == System.Data.ConnectionState.Open)
                            sqlConnection.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                _jobLogger.LogError(ex.Message);
            }

        }

        public class BathcDto
        {
            public Order_Order Order
            {
                get; set;
            }

            public List<Order_OrderGoods> OrderGoods
            {
                get; set;
            }
        }
    }

}
