using ServiceCenter.Extensions;
using ServiceCenter.Logs;
using ServiceCenter.Redis;
using ServiceCenter.SqlSugars;
using SqlSugar;
using WCS.Entity;
using TaskStatus = WCS.Entity.TaskStatus;

namespace WCS.WorkEngineering.Extensions
{
    /// <summary>
    /// 任务扩展
    /// </summary>
    public static class TaskExtension
    {
        /// <summary>
        /// 更新任务执行记录
        /// 同步更新历史任务
        /// </summary>
        /// <param name="task">任务信息</param>
        /// <param name="db">数据库上下文</param>
        /// <param name="curPoint">当前地址</param>
        /// <param name="desc">描述</param>
        public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarScopeProvider db, string curPoint, string desc) => task.AddWCS_TASK_DTL(db, curPoint, "", desc);

        /// <summary>
        /// 更新任务执行记录
        /// 同步更新历史任务
        /// </summary>
        /// <param name="task">任务信息</param>
        /// <param name="db">数据库上下文</param>
        /// <param name="curPoint">当前地址</param>
        /// <param name="nextPoint">下一个地址</param>
        /// <param name="desc">描述</param>
        public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarScopeProvider db, string curPoint, string nextPoint, string desc)
        {
            db.Insertable(new WCS_TaskDtl
            {
                ID = Guid.NewGuid(),
                ParentTaskCode = task.ID,
                CurPoint = curPoint,
                NextPoint = nextPoint,
                Desc = desc,
                AddWho = "WCS"
            }).SplitTable().ExecuteCommand();
            task.UpdateableOldTask(db);
        }

        /// <summary>
        ///  更新历史表数据
        /// </summary>
        /// <param name="taskInfo"></param>
        /// <param name="db"></param>
        public static void UpdateableOldTask(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db)
        {
            if (taskInfo.Status == TaskStatus.NewBuild) return;
            // 同步任务信息
            var taskOld = db.Queryable<WCS_TaskOld>().SplitTable(tabs => tabs.Take(2)).Where(v => v.Id == taskInfo.ID).OrderByDescending(v => v.AddTime).First();
            if (taskOld is not null)
            {
                if (taskInfo.Status >= TaskStatus.Finish) taskInfo.CompleteOrCancelTasks(db);
                else
                {
                    taskOld = taskInfo.Mapper<WCS_TaskOld, WCS_TaskInfo>();
                    taskOld.Id = taskInfo.ID;
                    db.Updateable(taskOld).Where(x => x.Id == taskOld.Id).SplitTable(x=>x.Take(2)).ExecuteCommand();
                }
            }
            else
            {
                throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID}，无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
            }
        }

        /// <summary>
        /// 完成或取消任务
        /// </summary>
        /// <param name="taskInfo"></param>
        /// <param name="db"></param>
        public static void CompleteOrCancelTasks(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db)
        {
            if (taskInfo.Status is not Entity.TaskStatus.Finish and not Entity.TaskStatus.Cancel) throw new KnownException("任务未完成或取消，无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
            // 任务完成或取消,进行相关同步动作
            var taskOld = db.Queryable<WCS_TaskOld>().SplitTable(tabs => tabs.Take(2)).Where(v => v.Id == taskInfo.ID).OrderByDescending(v => v.AddTime).First();
            if (taskOld is not null)
            {
                taskOld = taskInfo.Mapper<WCS_TaskOld, WCS_TaskInfo>();
                taskOld.Id = taskInfo.ID;
                //更新任务历史表,删除任务当前表
                db.Updateable(taskOld).SplitTable(x=>x.Take(2)).ExecuteCommand();
                db.Deleteable(taskInfo).ExecuteCommand();
            }
            else
            {
                throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID}，无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
            }
        }

        /// <summary>
        ///  更新表数据
        /// </summary>
        /// <param name="taskInfo"></param>
        /// <param name="db"></param>
        public static void Updateable(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db)
        {
            taskInfo.EditTime = DateTime.Now;
            taskInfo.EditWho = "WCS";
            db.Updateable(taskInfo).ExecuteCommand();
        }

        ///// <summary>
        /////  获取出库任务
        ///// </summary>
        ///// <param name="taskInfo">任务</param>
        ///// <param name="db">db</param>
        ///// <param name="allOutCode">可用出库站台</param>
        ///// <param name="floor">楼层</param>
        ///// <param name="obj">堆垛机</param>
        ///// <param name="index">递归次数</param>
        ///// <returns></returns>
        ///// <exception cref="KnownException"></exception>
        //public static WCS_TaskInfo GetOutTask(this WCS_TaskInfo taskInfo, SqlSugarHelper db, List<string> allOutCode, int floor, SRM obj, int index = 1)
        //{
        //    return task;
        //}

        /// <summary>
        /// 获取AGV任务ID
        /// </summary>
        /// <param name="db">db</param>
        /// <returns></returns>
        public static int GetAgvTaskId(this SqlSugarHelper db)
        {
            var id = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(v => v.Take(1)).Max(v => v.ID);
            return id + 1;
        }

        /// <summary>
        /// 更新任务执行记录
        /// </summary>
        /// <param name="task">任务信息</param>
        public static void UpdateRedisHash(this WCS_TaskInfo task)
        {
            var key = $"Hash:{task.ID}";
            if (task.Status >= TaskStatus.Finish)
            {
                RedisHub.WMS.Del(key);
            }
            else
            {
                RedisHub.WMS.HMSet(key, task.ToDic());
            }
        }

        #region 工字轮支线分流

        /// <summary>
        ///  初始化码垛信息
        /// </summary>
        /// <param name="task"></param>
        public static void InitStackStructure(this WCS_TaskInfo task, SqlSugarScopeProvider db)
        {
            var billBomsetinfo = db.Queryable<wms.sqlsugar.model.fj.BillBomsetinfo>().First(x => x.MatCode == task.MatCode);
            var billBomsetinfos = db.Queryable<wms.sqlsugar.model.fj.BillBomsetinfo>().Where(x => x.BomSetHdrId == billBomsetinfo.BomSetHdrId).ToList();
            var billBomsetgrp = db.Queryable<wms.sqlsugar.model.fj.BillBomsetgrp>().Single(x => x.Id == billBomsetinfo.BomSetHdrId);

            //开始构造垛形信息
            var palletizing = new WCS_Palletizing()
            {
                Code = billBomsetgrp.Code,
                ShortCode = billBomsetgrp.ShortCode,
                ProMaterCode = billBomsetgrp.ProMaterCode,
                TpTypeCode = billBomsetgrp.TpTypeCode,
                LayerCountQty = 2,
                StampType = billBomsetgrp.StampType,
                Finish = false,
                AddTime = DateTime.Now,
                TaskId = task.ID
            };
            palletizing = db.Insertable(palletizing).ExecuteReturnEntity();
            foreach (var item in billBomsetinfos.GroupBy(x => x.Row).OrderBy(x => x.Key))
            {
                var layerNo = item.Key <= 6 ? 1 : 2;
                //获取层信息
                var palletizingLayer = db.Queryable<WCS_PalletizingLayer>()
                    .Single(x => x.PalletizingId == palletizing.Id && x.LayerNo == layerNo);
                if (palletizingLayer == null)
                {
                    palletizingLayer = new WCS_PalletizingLayer()
                    {
                        LayerNo = layerNo,
                        PalletizingId = palletizing.Id
                    };
                    palletizingLayer = db.Insertable(palletizingLayer).ExecuteReturnEntity();
                }

                //获取行信息
                var palletizingRow = db.Queryable<WCS_PalletizingRow>()
                    .Single(x => x.PalletizingLayerId == palletizingLayer.Id && x.RowNo == item.Key);
                if (palletizingRow == null)
                {
                    palletizingRow = new WCS_PalletizingRow()
                    {
                        RowNo = item.Key,
                        PalletizingLayerId = palletizingLayer.Id
                    };
                    palletizingRow = db.Insertable(palletizingRow).ExecuteReturnEntity();
                }

                //重新查询最新的数据
                var layer = palletizingLayer;
                palletizingLayer = db.Queryable<WCS_PalletizingLayer>().Single(x => x.Id == layer.Id);
                var row = palletizingRow;
                palletizingRow = db.Queryable<WCS_PalletizingRow>().Single(x => x.Id == row.Id);

                //构造位信息
                foreach (var loc in item)
                {
                    var palletizingLoc = db.Queryable<WCS_PalletizingLoc>()
                        .Single(x => x.PalletizingRowId == palletizingRow.Id && x.XYNo == loc.XYNo);
                    if (palletizingLoc == null)
                    {
                        palletizingLoc = new WCS_PalletizingLoc()
                        {
                            IsEmpty = loc.IsEmpty != 0,
                            XYNo = loc.XYNo,
                            MatCode = loc.MatCode,
                            SideNum = loc.SideNum,
                            SpoolType = loc.SpoolType,
                            TaskId = task.ID,
                            PalletizingRowId = palletizingRow.Id,
                            Finish = false
                        };
                        palletizingLoc = db.Insertable(palletizingLoc).ExecuteReturnEntity();
                    }

                    //同步是否混合料行
                    palletizingRow.IsMixRow = loc.IsMixRow != 0;
                    db.Updateable(palletizingRow).ExecuteCommand();
                }
                //更新行信息
                palletizingRow = db.Queryable<WCS_PalletizingRow>().Includes(x => x.Locs).Single(x => x.Id == row.Id);
                palletizingRow.QtyMaxCount = palletizingRow.Locs.Count(x => !x.IsEmpty);
                palletizingRow.IsEmpty = palletizingRow.QtyMaxCount <= 0;
                palletizingRow.MatCodeList = palletizingRow.Locs.Select(x => x.MatCode).ToList().GetMatList();
                db.Updateable(palletizingRow).ExecuteCommand();
                //更新层信息
                palletizingLayer = db.Queryable<WCS_PalletizingLayer>().Includes(x => x.Rows, l => l.Locs).Single(x => x.Id == layer.Id);
                var count = palletizingLayer.Rows.Count(x => !x.IsEmpty); //计算所有不空数量
                palletizingLayer.IsEmpty = count <= 0;
                palletizingLayer.RowCountQty = palletizingLayer.Rows.Count;
                palletizingLayer.Finish = false;
                palletizingLayer.MatCodeList = palletizingLayer.Rows.SelectMany(x => x.Locs).Select(x => x.MatCode).ToList().GetMatList();

                db.Updateable(palletizingLayer).ExecuteCommand();
            }

            var palletizing1 = palletizing;
            palletizing = db.Queryable<WCS_Palletizing>().Includes(x => x.Layers, r => r.Rows, l => l.Locs).Single(x => x.Id == palletizing1.Id);
            //计算垛形信息
            var goods = palletizing.Layers.Select(x => x.Rows).SelectMany(x => x).Select(x => x.Locs).SelectMany(x => x).ToList();
            palletizing.CountQty = goods.Count(x => !x.IsEmpty);
            palletizing.MatCodeList = palletizing.Layers.SelectMany(x => x.Rows).SelectMany(x => x.Locs).Select(x => x.MatCode).ToList().GetMatList();
            db.Updateable(palletizing).ExecuteCommand();
        }

        public static string GetMatList(this List<string> matList)
        {
            return matList.Distinct().Aggregate("", (current, mat) => current + $"[{mat}]");
        }

        #endregion 工字轮支线分流
    }

    /// <summary>
    ///  垛形位信息
    /// </summary>
    public class StackPosInfo
    {
        /// <summary>
        ///  任务号
        /// </summary>
        public int TaskNumber { get; set; }

        /// <summary>
        /// 是否空置
        /// </summary>
        public bool IsEmpty { get; set; }

        /// <summary>
        /// 坐标号
        /// </summary>
        public string XYNo { get; set; }

        /// <summary>
        /// 物料编码
        /// </summary>
        public string MatCode { get; set; }

        /// <summary>
        /// 正反面
        /// </summary>
        public int SideNum { get; set; }

        /// <summary>
        /// 工字轮类型
        /// </summary>
        public string SpoolType { get; set; }

        /// <summary>
        ///  是否结束
        /// </summary>
        public bool Finish { get; set; }
    }
}
