using XYY.TaskTrack.Standard.TaskModel;
using System.Linq;
using XYY.TaskTrack.Standard;
using System;
using XYY.Core.Standard.Data.Infrastructure;
using Dapper;
using System.Threading.Tasks;
using System.Collections.Generic;
using Nest;
using XYY.Data.Standard.Tasks;
using XYY.Service.Standard.First.DB;
using Microsoft.Extensions.Logging;
using XYY.Data.Model.Standard.Tracking;

namespace XYY.Service.Standard.First.JobSubscribe
{

    public interface IJobSubscribe : IBaseConsumer<Job_LadingBillLogistics>
    {

    }


    public class JobSubscribe : BaseConsumer<Job_LadingBillLogistics>, IJobSubscribe
    {
        private IUnitOfWork _unitOfWork;
        private IFirstDB _firstDB;
        private ITaskTrackDataRepository _taskTrackData;
        private ILogger<JobSubscribe> _jobLogger;
        private IFirstDB2 _firstDB2;

        public JobSubscribe(IMQManager mq, IFirstDB firstDB, IUnitOfWork unitOfWork, ITaskTrackDataRepository taskTrackData, ILogger<JobSubscribe> jobLogger
            , IFirstDB2 firstDB2) : base(mq)
        {
            _unitOfWork = unitOfWork;
            _firstDB = firstDB;
            _taskTrackData = taskTrackData;
            _jobLogger = jobLogger;
            _firstDB2 = firstDB2;
        }

        public override async Task Consume(Job_LadingBillLogistics message)
        {

            _jobLogger.LogWarning("接收到提单信息更新，" + message.Jobs.Count + "条信息");
            List<dynamic> firstTrackings = new List<dynamic>();
            string sql = $@"select d.TrafficTime,d.CreateTime,c.LadingBillNumber,a.TrackingNumber,a.Id,a.ReceiverCountryCode,d.DepartTime,d.ArrivalTime,d.ClearanceTime from Order_Order(nolock) a join Logistics_Boxdetail(nolock) b on a.id = b.orderid join logistics_box(nolock) c on b.boxid=c.id
                              join Logistics_LadingBill(nolock) d on d.LadingBillNumber = c.LadingBillNumber
                           where d.LadingBillNumber in @ladingBillNumber  and d.IsDeleted=0
                            ";
            var array = message.Jobs.Select(x => x.LadingBillNumber).ToArray();
            //var mapping = (await _unitOfWork.QueryBySqlAsync<object>(sql,null, new
            //{
            //    ladingBillNumber = array
            //})).ToList();
            firstTrackings = (await _unitOfWork.QueryBySqlAsync<dynamic>(sql, 0,
                new
                {
                    ladingBillNumber = array
                })).ToList();
            foreach (var ladingBillNumber in message.Jobs)
            {
                try
                {
                    _jobLogger.LogWarning("导入提单头程信息:" + ladingBillNumber.LadingBillNumber);
                    var items = firstTrackings.Where(x =>
                    x.LadingBillNumber == ladingBillNumber.LadingBillNumber

                    ).ToList();
                    if (items.Count > 0)
                    {
                        var logs = GetLogs(items, ladingBillNumber);
                        //增加覆写操作，补充记录覆盖
                        await GetDBSupplementLogs(items, ladingBillNumber);
                        if (await AddFristLogAsEs(logs))
                        {
                            //await _taskTrackData.Success(1, message.Id);
                            await _unitOfWork.ExecuteAsync($"update Logistics_LadingBill set  DepartTime=@DepartTime," +

                                $" ArrivalTime=@ArrivalTime,ClearanceTime=@ClearanceTime,CustomsClearanceTime=@CustomsClearanceTime,LeaveWarehouseTime=@LeaveWarehouseTime,TrafficTime=@TrafficTime where LadingBillNumber=@LadingBillNumber",
                                new
                                {
                                    DepartTime = ladingBillNumber.DepartTime,
                                    ArrivalTime = ladingBillNumber.ArrivalTime,
                                    ClearanceTime = ladingBillNumber.ClearanceTime,
                                    CustomsClearanceTime = ladingBillNumber.CustomsClearanceTime,
                                    LeaveWarehouseTime = ladingBillNumber.LeaveWarehouseTime,
                                    LadingBillNumber = ladingBillNumber.LadingBillNumber,
                                    TrafficTime = ladingBillNumber.TrafficTime
                                });
                        }
                        else
                        {
                            MessageHelper.SendWXMsg("提单轨迹同步失败-运单明细轨迹生成失败",
                                $"{ladingBillNumber}",
                                new string[] { "fanlihang"
                                        , "ZhangCong", "jie", "YanXiaoYan", "HeHuiQun", "hailey", "Mai" ,
                                        "JUAN","zhaokaining"});
                            _jobLogger.LogError("导入提单头程信息失败:" + ladingBillNumber.LadingBillNumber);
                            //await _taskTrackData.Error(1, message.Id);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageHelper.SendWXMsg("提单轨迹同步失败-提单数据更新失败",
                        $"{ladingBillNumber}" + ex.Message,
                        new string[] { "fanlihang"
                                        , "ZhangCong", "jie", "YanXiaoYan", "HeHuiQun", "hailey", "Mai" ,
                                        "JUAN","zhaokaining"});
                }
            }
            MessageHelper.SendWXMsg("提单轨迹同步-导入提单头程信息完毕", "导入提单头程信息完毕",
                new string[] { "fanlihang"
                                        , "ZhangCong", "jie", "YanXiaoYan", "HeHuiQun", "hailey", "Mai" ,
                                        "JUAN","zhaokaining"});
            _jobLogger.LogWarning("导入提单头程信息完毕");

        }

        public static List<Logistics_TraceGroup> GetLogs2(List<dynamic> orders, Job_LadingBillLogisticsItem bill, bool isESB = false)
        {
            List<Logistics_TraceGroup> insertLogs = new List<Logistics_TraceGroup>();

            foreach (var tn in orders)
            {
                var g = new Logistics_TraceGroup
                {
                    TrackingNumber = isESB ? tn.TransferNumber : tn.TrackingNumber,
                    CustomerOrderNo = tn.CustomerOrderNo,
                    List = new List<EsLogisticsTrackingLog>()
                };
                insertLogs.Add(g);

                if (bill.ArrivalTime.HasValue && bill.updatedNode.Contains("ArrivalTime"))
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.ArrivalTime.Value,
                        Status = 5,
                        StatusString = "Item is being presented to customs.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }

                if (bill.DepartTime.HasValue && bill.updatedNode.Contains("DepartTime"))
                {
                    var g2 = new Logistics_TraceGroup
                    {
                        TrackingNumber = tn.TrackingNumber,
                        CustomerOrderNo = tn.CustomerOrderNo,
                        List = new List<EsLogisticsTrackingLog>()
                    };
                    insertLogs.Add(g2);
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.DepartTime.Value,
                        Status = 4,
                        StatusString = "Item is ready for departure.",
                        Location = "广州",
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }

                if (bill.ClearanceTime.HasValue && bill.updatedNode.Contains("ClearanceTime"))
                {
                    var g3 = new Logistics_TraceGroup
                    {
                        TrackingNumber = tn.TrackingNumber,
                        CustomerOrderNo = tn.CustomerOrderNo,
                        List = new List<EsLogisticsTrackingLog>()
                    };
                    insertLogs.Add(g3);
                    g3.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.ClearanceTime.Value,
                        Status = 6,
                        StatusString = "Item was released from customs.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }

                if (bill.TrafficTime.HasValue && bill.updatedNode.Contains("TrafficTime"))
                {
                    var g3 = new Logistics_TraceGroup
                    {
                        TrackingNumber = tn.TrackingNumber,
                        CustomerOrderNo = tn.CustomerOrderNo,
                        List = new List<EsLogisticsTrackingLog>()
                    };
                    insertLogs.Add(g3);
                    g3.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.TrafficTime.Value,
                        Status = 11,
                        StatusString = "Arrived Export Airport.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }
            }

            return insertLogs;
        }


        public static List<Logistics_TraceGroup> GetLogs(List<dynamic> orders, Job_LadingBillLogisticsItem bill)
        {
            List<Logistics_TraceGroup> insertLogs = new List<Logistics_TraceGroup>();
            foreach (var tn in orders)
            {
                var g = new Logistics_TraceGroup
                {
                    TrackingNumber = tn.TrackingNumber,
                    CustomerOrderNo = tn.CustomerOrderNo,
                    List = new List<EsLogisticsTrackingLog>()
                };
                insertLogs.Add(g);


                g.List.Add(new EsLogisticsTrackingLog
                {
                    CreateTime = DateTime.Now,
                    TriggerTime = bill.CreateTime,
                    Status = 4,
                    Location = "China",
                    OrderId = tn.Id,
                    ChannelId = 0,
                    TrackingNumber = tn.TrackingNumber,
                    StatusString = "During domestic transportation",
                    Uid = Guid.NewGuid().ToString()
                });

                if (bill.ArrivalTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.ArrivalTime.Value,
                        Status = 5,
                        StatusString = "Item is being presented to customs.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }

                if (bill.DepartTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.DepartTime.Value,
                        Status = 4,
                        StatusString = "Item is ready for departure.",
                        Location = "广州",
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }
                if (bill.SubmitClearanceTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.SubmitClearanceTime.Value,
                        Status = 5,
                        StatusString = "Item is awaiting customs clearance.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }
                if (bill.ClearanceTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.ClearanceTime.Value,
                        Status = 6,
                        StatusString = "Item was released from customs.",
                        Location = tn.ReceiverCountryCode,
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }
                if (bill.CustomsClearanceTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.CustomsClearanceTime.Value,
                        Status = 4,
                        StatusString = "it is under customs clearance.",
                        Location = "CN",
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }

                if (bill.TrafficTime.HasValue)
                {
                    g.List.Add(new EsLogisticsTrackingLog
                    {
                        CreateTime = DateTime.Now,
                        TriggerTime = bill.TrafficTime.Value,
                        Status = 4,
                        StatusString = "Arrived Export Airport.",
                        Location = "CN",
                        OrderId = tn.Id,
                        ChannelId = 0,
                        TrackingNumber = tn.TrackingNumber,
                        Uid = Guid.NewGuid().ToString()
                    });
                }


            }

            return insertLogs;
        }

        public async Task<bool> AddFristLogAsEs(List<Logistics_TraceGroup> insertLogs)
        {
            bool isSuccess = await _firstDB.DeleteAndUpdate(insertLogs);
            return isSuccess;
        }
        public async Task<bool> GetDBSupplementLogs(List<dynamic> orders, Job_LadingBillLogisticsItem bill)
        {
            var batchQty = 500.0;
            bool result = true;
            try
            {
                for (int i = 0; i < Math.Ceiling(orders.Count / batchQty); i++)
                {
                    List<Logistics_TraceGroup> coverLogs = new List<Logistics_TraceGroup>();
                    var tempOrders = orders.Skip(i * (int)batchQty).Take((int)batchQty).ToList();
                    string sql = @"select * from Logistics_Trace_SupplementLog(nolock) where TrackingNumber in @TrackingNumber and IsSuccess=1 and isnull(IsCover,0)=0";
                    var SupplementLogs = await _unitOfWork.QueryBySqlAsync<Logistics_Trace_SupplementLog>(sql, null, new { TrackingNumber = tempOrders.Select(x => x.TrackingNumber) });
                    if (SupplementLogs == null || SupplementLogs.Count() == 0) { continue; }//无数据继续下一批
                    var TrackingNumberDis = tempOrders.Select(x => x.TrackingNumber).Distinct().ToList();
                    foreach (var item in TrackingNumberDis)
                    {
                        var tempOrder = tempOrders.Where(x => x.TrackingNumber == item).FirstOrDefault();
                        var tempLogs = SupplementLogs.Where(x => x.TrackingNumber == item).ToList();
                        List<int> Ids = new List<int>();
                        tempLogs.ForEach(log =>
                        {
                            if (log.JudgmentNode == (int)JudgmentNode.装箱 && bill.DepartTime.HasValue && bill.DepartTime < log.TrackSupplementTime) { log.IsCover = true; }
                            else if (log.JudgmentNode == (int)JudgmentNode.国内转运 && bill.DepartTime.HasValue && bill.DepartTime < log.TrackSupplementTime) { log.IsCover = true; }
                            else if (log.JudgmentNode == (int)JudgmentNode.离港时间 && bill.DepartTime.HasValue && bill.DepartTime < log.TrackSupplementTime) { log.IsCover = true; }
                            else if (log.JudgmentNode == (int)JudgmentNode.到港时间 && bill.ArrivalTime.HasValue && bill.ArrivalTime < log.TrackSupplementTime) { log.IsCover = true; }
                            else if (log.JudgmentNode == (int)JudgmentNode.清关时间 && bill.ClearanceTime.HasValue && bill.ClearanceTime < log.TrackSupplementTime) { log.IsCover = true; }

                            if (log.IsCover) { Ids.Add(log.Id); }
                        });
                        if (tempLogs.All(x => x.IsCover))
                        { await _firstDB2.DeleteAsync(item); }
                        else
                        {
                            foreach (var es in tempLogs.Where(x => !x.IsCover).ToList())
                            {
                                coverLogs.Add(GetSupplementLog(tempOrder, es.TrackSupplementText, es.TrackSupplementTime, es.TrackSupplementLocation == TrackSupplementLocation.国内.GetValue() ? "china" : tempOrder.ReceiverCountryCode));
                            }
                        }
                        if (Ids.Count() > 0)
                        { await _unitOfWork.ExecuteAsync(" update Logistics_Trace_SupplementLog set IsCover=1 where Id in (" + string.Join(",", Ids) + ")"); }

                    }
                    if (coverLogs.Count > 0) { await _firstDB2.DeleteAndUpdate(coverLogs); }
                }
            }
            catch (Exception ex)
            {
                result = false;
            }

            return result;
        }
        private Logistics_TraceGroup GetSupplementLog(dynamic order, string StatusString, DateTime trajectoryTime, string locaiton)
        {
            var g = new Logistics_TraceGroup
            {
                TrackingNumber = order.TrackingNumber,
                CustomerOrderNo = order.CustomerOrderNo,
                List = new List<EsLogisticsTrackingLog>()
            };

            g.List.Add(new EsLogisticsTrackingLog
            {
                CreateTime = DateTime.Now,
                TriggerTime = trajectoryTime,
                Status = 5,
                StatusString = StatusString,
                Location = locaiton ?? order.ReceiverCountryCode,
                OrderId = order.Id,
                ChannelId = 0,
                TrackingNumber = order.TrackingNumber,
                Uid = Guid.NewGuid().ToString()
            });
            return g;
        }
    }

    #region 头程补充

    public interface ITrackSupplement : IBaseConsumer<TrackSupplementRequest>
    {

    }

    public class TrackSupplement : BaseConsumer<TrackSupplementRequest>, ITrackSupplement
    {
        private IUnitOfWork _unitOfWork;
        private IFirstDB2 _firstDB2;
        private ITaskTrackDataRepository _taskTrackData;
        private ILogger<TrackSupplement> _jobLogger;

        public TrackSupplement(IMQManager mq, IFirstDB2 firstDB2, IUnitOfWork unitOfWork, ITaskTrackDataRepository taskTrackData, ILogger<TrackSupplement> jobLogger) : base(mq)
        {
            _unitOfWork = unitOfWork;
            _firstDB2 = firstDB2;
            _taskTrackData = taskTrackData;
            _jobLogger = jobLogger;
        }
        public override async Task Consume(TrackSupplementRequest message)
        {
            List<dynamic> firstTrackings = new List<dynamic>();
            string DataProcessingMethod = "运单号处理，受影响行数{0}";
            try
            {
                if (!string.IsNullOrEmpty(message.trackingNumber))
                {
                    var tempNumber = message.trackingNumber.Split(new string[] { Environment.NewLine, "\n", "," }, StringSplitOptions.None);
                    tempNumber = tempNumber.Where(x => !string.IsNullOrEmpty(x)).ToArray();
                    var xml = string.Join("\r\n", tempNumber.Select(x => $"<NumberList><Number>{x}</Number></NumberList>"));
                    string sql2 = @"

if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..#temp_searchs') and type='U')
    drop table #temp_searchs
if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..#tempOrders') and type='U')
    drop table #tempOrders

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))

                                             select * into #tempOrders from (
                                            select * from  Order_Order(nolock) 
	                                             join #temp_searchs(nolock) on Order_Order.CustomerOrderNo = #temp_searchs.Number
	                                             union all
	                                             select * from  Order_Order(nolock) 
	                                             join #temp_searchs(nolock) on Order_Order.TransferNumber = #temp_searchs.Number
	                                            union all
	                                             select * from  Order_Order(nolock) 
	                                             join #temp_searchs(nolock) on Order_Order.TrackingNumber = #temp_searchs.Number)zz";



                    //去掉相关数组
                    string sql = sql2.Formater(xml) + $@" select a.TrackingNumber,a.Id,a.ReceiverCountryCode,a.CustomerOrderNo from Order_Order(nolock) a 
                                join #tempOrders b on a.Id=b.Id";
                    firstTrackings = (await _unitOfWork.QueryBySqlAsync<dynamic>(sql, null,
                        new { TrackingNumber = tempNumber })).ToList();
                }
                else
                {
                    string sql = $@"select c.LadingBillNumber,a.TrackingNumber,a.Id,a.ReceiverCountryCode,d.DepartTime,d.ArrivalTime,d.ClearanceTime,a.CustomerOrderNo from Order_Order(nolock) a join Logistics_Boxdetail(nolock) b on a.id = b.orderid join logistics_box(nolock) c on b.boxid=c.id
                              join Logistics_LadingBill(nolock) d on d.LadingBillNumber = c.LadingBillNumber
                           where d.LadingBillNumber=@ladingBillNumber  and d.IsDeleted=0
                            ";
                    firstTrackings = (await _unitOfWork.QueryBySqlAsync<dynamic>(sql, null,
                        new { ladingBillNumber = message.LadingBillNumber })).ToList();
                    DataProcessingMethod = "提单号处理，受影响行数{0}";
                }
                List<Logistics_TraceGroup> datas = new List<Logistics_TraceGroup>();
                foreach (var item in firstTrackings)
                {
                    var log = GetLog(item, message.StatusString, message.trajectoryTime, message.Loaction);
                    datas.Add(log);
                }
                if (!await AddFristLogAsEs(datas))
                {
                    _jobLogger.LogError("增加头程信息失败:");
                }
                _jobLogger.LogWarning("增加头程信息成功！" + string.Format(DataProcessingMethod, firstTrackings.Count()));
            }
            catch (Exception ex)
            {
                _jobLogger.LogError("头程补充失败" + message.LadingBillNumber + "$$" + message.trackingNumber);
            }
        }
        public async Task<bool> AddFristLogAsEs(List<Logistics_TraceGroup> insertLogs)
        {
            bool isSuccess = await _firstDB2.InsertAndUpdate(insertLogs);
            return isSuccess;
        }

        public static Logistics_TraceGroup GetLog(dynamic order, string StatusString, DateTime trajectoryTime, string locaiton)
        {
            var g = new Logistics_TraceGroup
            {
                TrackingNumber = order.TrackingNumber,
                CustomerOrderNo = order.CustomerOrderNo,
                List = new List<EsLogisticsTrackingLog>()
            };

            g.List.Add(new EsLogisticsTrackingLog
            {
                CreateTime = DateTime.Now,
                TriggerTime = trajectoryTime,
                Status = 5,
                StatusString = StatusString,
                Location = locaiton ?? order.ReceiverCountryCode,
                OrderId = order.Id,
                ChannelId = 0,
                TrackingNumber = order.TrackingNumber,
                Uid = Guid.NewGuid().ToString()
            });
            return g;
        }
    }
    #endregion
}
