using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using wcftest.BussinessExtension.Common;
using wcftest.EnumDefine;
using wcftest.orm;
namespace wcftest.BussinessExtension.Handle
{
    /// 
    /// 自动移库处理类
    /// 
    public class AutoMoveLocationHandler
    {
        private static object ojb = new object();
        private static object ojb_AddTask = new object();
        /// 
        /// 获取当前正在执行的闲时移库任务
        /// 
        /// 
        /// 
        public static Wms_FreeTimeMoveLocationTask GetCurExcuteFreeTimeMoveLocationTask(dbModel mod)
        {
            lock (ojb)
            {
                var queryMoveStatus = (int)MoveStatusEnum.执行中;
                var task = mod.Wms_FreeTimeMoveLocationTask.Where(x => x.MoveStatus == queryMoveStatus).FirstOrDefault();
                if (task != null)
                {
                    //判断这个是否已经到期了
                    if (task.StartTime == null)
                    {
                        throw new Exception("任务已执行中,但是开始时间为NULL");
                    }
                    var startTime = Convert.ToDateTime(task.StartTime);
                    int runTime = Convert.ToInt32(task.RunTime);
                    var planEndTime = startTime.AddMinutes(runTime);//计划结束日期
                    if (planEndTime <= DateTime.Now)
                    {
                        //强制结束
                        task.LastModifier = "调度系统";
                        task.LastModifyTime = DateTime.Now;
                        task.Remark = "自动到期结束";
                        MoveStatusEnum moveStatusEnum = MoveStatusEnum.执行完毕;
                        task.MoveStatus = (int)moveStatusEnum;
                        task.MoveStatusName = moveStatusEnum.ToString();
                        var endTime = DateTime.Now;
                        task.EndTime = endTime;
                        //计算持续时长(分钟)
                        if (task.StartTime != null)
                        {
                            TimeSpan ts = ((DateTime)endTime - (DateTime)task.StartTime);
                            task.ActualTime = Convert.ToInt32(ts.TotalMinutes);
                        }
                        //计算已完成数量
                        var count = mod.Wms_FreeTimeMoveLocationTaskDetails.Where(x => x.MainFreeMoveId == task.ID).Count();
                        task.FinishQuantity = count;
                        mod.SaveChanges();
                        return null;
                    }
                    else
                    {//还不到时间,继续执行
                        return task;
                    }
                }
                return null;
            }
        }
        /// 
        /// 是否前面存在未结束的移库任务
        /// 
        /// 
        /// 
        /// 
        public static bool IsNeedCreateNewMoveTask(dbModel mod, string areaCode)
        {
            var list = BussinessExtension.GetDoingTaskList(mod, Convert.ToInt32(areaCode), TaskTypeEnum.移库);
            if (list != null && list.Count > 0)
            {
                return false;
            }
            return true;
        }
        /// 
        /// 高库位去合适库位的移库
        /// 
        /// 
        /// 
        /// 
        public static bool DoForHighLocation(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask)
        {
            /*
             * 1、分区处理
             * 2、优先按照库位高度匹配进行移库
             * 3、其次按照库存平衡进行移库
             */
            //策略1:读取高度不匹配的数据
            List _prdListForIsInMoreHighPosition = new List();
            var queryIsLocked = (int)IsLockedEnum.未锁定;
            var queryIsFreeze = (int)IsFreezeEnum.有货;
            var queryEnable = (int)usable.可用;
            var prdList = mod.vvBase_ProductPosition.Where(x => x.PositionName != SysGlole.PositionName_SHZCQ && x.IsInMoreHighPosition == 1 && x.AreaCode == areaCode
                && x.IsLocked == queryIsLocked && x.IsFreeze == queryIsFreeze).ToList();
            if (prdList == null || prdList.Count() == 0)
            {
                return false;
            }
            //排除掉有任务占用的情况,优化  【EditBy shaocx,2022-09-21】
            _prdListForIsInMoreHighPosition = BussinessExtension.FilterPositionTakeDoingTask(prdList, mod, Convert.ToInt32(areaCode));
            if (_prdListForIsInMoreHighPosition.Count > 0)
            {//进行移库
                //只取一个进行移库
                foreach (var item in _prdListForIsInMoreHighPosition)
                {
                    var prod_position = mod.Base_ProductPosition.Where(x => x.ProductPosition_Id == item.ProductPosition_Id).FirstOrDefault();
                    Base_Position source_position = mod.Base_Position.Where(x => x.PositionName == prod_position.PositionName).FirstOrDefault();
                    if (source_position.Enable != queryEnable)
                    {
                        continue;//不可用库位,就直接跳过
                    }
                    var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, source_position.PositionName);
                    if (validateExistPlaceTaskList == false)
                    {
                        continue;//已经执行过了,就直接跳过
                    }
                    var result = AddTaskForMoveStore("", AutoMoveLocationReasonEnum.高库位去合适库位, freeTimeMoveLocationTask, mod, "", source_position, Convert.ToInt32(areaCode), prod_position, item);
                    if (result)
                    {
                        return true;//执行成功了,就直接结束,返回true
                    }
                }
            }
            return false;
        }
        /// 
        /// 库存平衡的移库
        /// 
        /// 
        /// 
        /// 
        public static bool DoForAutoBalance(dbModel mod, string areaCode, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask)
        {
            /*
             * 1、分区处理
             * 2、优先按照库位高度匹配进行移库
             * 3、其次按照库存平衡进行移库
             */
            //策略2:按照库存平衡进行移库
            List _prdList = new List();
            var queryIsLocked = (int)IsLockedEnum.未锁定;
            var queryIsFreeze = (int)IsFreezeEnum.有货;
            var queryEnable = (int)usable.可用;
            var prdList = mod.vvBase_ProductPosition.Where(x => x.PositionName != SysGlole.PositionName_SHZCQ && x.AreaCode == areaCode
                && x.IsLocked == queryIsLocked && x.IsFreeze == queryIsFreeze).ToList();
            if (prdList == null || prdList.Count() == 0)
            {
                return false;
            }
            //排除掉有任务占用的情况,优化  【EditBy shaocx,2022-09-21】
            _prdList = BussinessExtension.FilterPositionTakeDoingTask(prdList, mod, Convert.ToInt32(areaCode));
            if (_prdList.Count > 0)
            {//进行移库
                var _prdList_01 = _prdList.Where(x => x.ShelveCode == "01").ToList();
                var _prdList_02 = _prdList.Where(x => x.ShelveCode == "02").ToList();
                int _prdList_01_Count = _prdList_01 == null ? 0 : _prdList_01.Count;
                int _prdList_02_Count = _prdList_02 == null ? 0 : _prdList_02.Count;
                string sourceShelveCode = "", toShelveCode = "";
                if (_prdList_01_Count > _prdList_02_Count)
                {
                    sourceShelveCode = "01";
                    toShelveCode = "02";
                }
                else if (_prdList_01_Count < _prdList_02_Count)
                {
                    sourceShelveCode = "02";
                    toShelveCode = "01";
                }
                else
                {
                    return false;
                }
                if (!string.IsNullOrEmpty(sourceShelveCode))
                {
                    //只取一个进行移库
                    foreach (var item in _prdList)
                    {
                        var prod_position = mod.Base_ProductPosition.Where(x => x.ProductPosition_Id == item.ProductPosition_Id).FirstOrDefault();
                        Base_Position source_position = mod.Base_Position.Where(x => x.PositionName == prod_position.PositionName).FirstOrDefault();
                        if (source_position.Enable != queryEnable)
                        {
                            continue;//不可用库位,就直接跳过
                        }
                        var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, source_position.PositionName);
                        if (validateExistPlaceTaskList == false)
                        {
                            continue;//已经执行过了,就直接跳过
                        }
                        var result = AddTaskForMoveStore(toShelveCode, AutoMoveLocationReasonEnum.库存平衡, freeTimeMoveLocationTask, mod, "", source_position, Convert.ToInt32(areaCode), prod_position, item);
                        if (result)
                        {
                            return true;//执行成功了,就直接结束,返回true
                        }
                    }
                }
            }
            return false;
        }
        /// 
        /// 
        /// 
        /// 按照排数过滤
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        private static bool AddTaskForMoveStore(string filter_shelveCode, AutoMoveLocationReasonEnum autoMoveLocationReason, Wms_FreeTimeMoveLocationTask freeTimeMoveLocationTask, dbModel mod, string username, Base_Position source_position, int areaCode, Base_ProductPosition prod_position, vvBase_ProductPosition store)
        {
            lock (ojb_AddTask)
            {
                var sourcePlace = store.PositionName.Substring(2);
                var findEmptyReason = "";
                bool isInMoreHighPosition = false;
                //返回格式: 格式: 01-03-01
                if (store.PhysicsHeight == null)
                {
                    return false;//说明没有光电检测高度
                }
                #region 事务
                using (var trans = mod.Database.BeginTransaction())
                {
                    try
                    {
                        var toplace = FindEmptyLocationHandler.findStorage(mod, filter_shelveCode, false, ref isInMoreHighPosition, ref findEmptyReason, Convert.ToInt32(areaCode),
                    Convert.ToInt32(prod_position.PlateType), Convert.ToInt32(store.PhysicsHeight));//分配库位
                        if (isInMoreHighPosition)
                        {//表示入了不匹配自己高度的库位,找的是更高的库位,不处理
                            return false;
                        }
                        if (string.IsNullOrEmpty(toplace))
                        {//未找到库位
                            return false;
                        }
                        var validateExistPlaceTaskList = FreeTimeMoveLocationTaskHandler.ValidateExistPlaceTaskList(mod, freeTimeMoveLocationTask, areaCode + "-" + toplace);
                        if (validateExistPlaceTaskList == false)
                        {
                            return false;//已经执行过了,就直接跳过
                        }
                        #region 写入任务表
                        Task_Queue addTask = new Task_Queue();
                        addTask.BillCode = "移库";//来源单号
                        addTask.TaskType = ((int)TaskTypeEnum.移库).ToString();
                        addTask.PlateType = prod_position.PlateType;//器具种类-大托盘小托盘
                        addTask.PlateCode = prod_position.PlateCode;//母托盘编号
                        addTask.Bill_Id = 0;// 单据id
                        addTask.OrderNumber = 0;//任务执行优先级
                        addTask.TaskStatus = "未下发";//任务状态
                        addTask.FromPositionName = sourcePlace;//起始地址
                        addTask.ToPositionName = toplace;//目标地址给空返回测量高度后重新写入
                        addTask.Direction = areaCode == 1 ? "2" : "4";//出库不需要托盘高度
                        addTask.DoCount = areaCode;//库区
                        addTask.CreateDate = DateTime.Now;
                        addTask.Creator = "系统";
                        addTask.UserProduct_Id = 1007;//账套id 老谢bug  
                        mod.Task_Queue.Add(addTask);
                        int result = mod.SaveChanges();
                        if (result == 0)
                        {
                            throw new Exception("新增任务表失败");
                        }
                        #endregion
                        #region 写入 闲时移库任务明细表
                        Wms_FreeTimeMoveLocationTaskDetails details = new Wms_FreeTimeMoveLocationTaskDetails()
                        {
                            AreaCode = areaCode.ToString(),
                            SoucePlace = areaCode + "-" + sourcePlace,
                            ToPlace = areaCode + "-" + toplace,
                            CreateTime = DateTime.Now,
                            Creator = "",
                            LastModifier = "",
                            LastModifyTime = DateTime.Now,
                            MainFreeMoveId = freeTimeMoveLocationTask.ID,
                            MoveRemark = autoMoveLocationReason.ToString(),
                            Remark = "初始",
                            Task_Id = addTask.Task_Id
                        };
                        mod.Wms_FreeTimeMoveLocationTaskDetails.Add(details);
                        #endregion
                        //添加日志
                        SystemHelper.addOperation(mod, username, "移库:从" + sourcePlace + "到" + toplace, "移库,库区:" + areaCode);
                        //锁定库位(源库位+目标库位)
                        var query_toplace = areaCode + "-" + toplace;
                        Base_Position to_position = mod.Base_Position.Where(x => x.PositionName == query_toplace).FirstOrDefault();
                        to_position.IsLocked = 1;//找到空库位时,库位锁定!
                        to_position.Remark = "闲时移库-找到空库位时,库位锁定!";
                        //to_position.IsFreeze = 1;
                        to_position.IsFreeze = (int)IsFreezeEnum.有货;
                        source_position.IsLocked = 1;//找到空库位时,库位锁定!
                        source_position.Remark = "闲时移库-找到空库位时,库位锁定!";
                        //更新闲时移库表的次数
                        if (freeTimeMoveLocationTask.FinishQuantity == null)
                        {
                            freeTimeMoveLocationTask.FinishQuantity = 1;
                        }
                        else
                        {
                            freeTimeMoveLocationTask.FinishQuantity = Convert.ToInt32(freeTimeMoveLocationTask.FinishQuantity) + 1;
                        }
                        result = mod.SaveChanges();
                        if (result == 0)
                        {
                            throw new Exception("保存失败");
                        }
                        trans.Commit();
                        return true;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        throw ex;
                    }
                }
                #endregion
            }
        }
    }
}