using ServiceCenter.Extensions;
using ServiceCenter.Logs;
using ServiceCenter.SqlSugars;
using System.ComponentModel;
using WCS.Core;
using WCS.Entity;
using WCS.Entity.Protocol.Station;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.Worlds;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace WCS.WorkEngineering.Systems
{
    /// <summary>
    ///  桁架缓存放行点
    /// </summary>
    [BelongTo(typeof(SortingPalletizingWorld))]
    [Description("桁架缓存放行点")]
    public class 桁架缓存放行点 : DeviceSystem<Device<IStation520, IStation521, IStation523>>
    {
        protected override bool ParallelDo => true;

        /// <summary>
        ///  取货点设备集合
        /// </summary>
        private readonly Dictionary<Device<IStation524, IStation523>, List<Device<IStation524, IStation523>>> _cacheDevices = new();

        public override void Do(Device<IStation520, IStation521, IStation523> obj)
        {
            if (obj.Data.VoucherNo != obj.Data2.VoucherNo)
            {
                World.Log($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}");
                return;
            }

            if (obj.Data3.Status.HasFlag(StationStatus.Run))
            {
                World.Log("设备运行中");
                return;
            }

            if (obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 0)
            {
                World.Log("有光电无请求");
                return;
            }

            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 1)
            {
                World.Log("无光电有请求");
                return;
            }

            if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status))
            {
                World.Log("站台货物信息与实际占用不一致");
                return;
            }

            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status))
            {
                World.Log("无光电");
                return;
            }

            if (obj.Data2.Request != 1)
            {
                World.Log("无请求");
                return;
            }

            var nextDev = new Device<IStation524, IStation523>(obj.Entity.Targets.FirstOrDefault()!, World);
            if (nextDev.Data2.Status1.HasFlag(StationStatus1.IsLock))
            {
                World.Log($"{nextDev.Entity.Code}桁架未取货完成，线体锁定中");
                return;
            }

            //获取当前缓存线信息对应设备号的下一个地址
            var devCode = Device.All.Single(x => x.Code == obj.Entity.Code).Targets.FirstOrDefault();
            var nextCode = obj.Entity.Targets.FirstOrDefault().Code.ToShort();

            #region 计算当前缓存线是否已全部分配任务

            SqlSugarHelper.Do(_db =>
            {
                var db = _db.Default;
                var cacheLine = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).Single(x => x.LocationNo == obj.Entity.Code.ToShort());
                //是否所有的位已全部分配位置
                if (cacheLine != null && cacheLine.Locations.All(x => (x is { IsEmpty: false, InStock: true }) || (x.AddTime < DateTime.Now.AddHours(-6))))
                {
                    //判断下一个地址当前是否有对应的任务
                    if (db.Queryable<WCS_CacheLine>().Any(x => x.LocationNo == nextCode && x.IsTruss == false)) return;
                    //下一个地址没有光电
                    var dev = new Device<IStation523>(Device.All.First(x => x.Code == nextCode.ToString()), World);
                    if (dev.Data.Status.HasFlag(StationStatus.PH_Status)) return;
                    //没有对应的任务，开始释放缓存
                    cacheLine.InStock = true;
                    cacheLine.LocationNo = devCode.Code.ToShort();
                    cacheLine.EditTime = DateTime.Now;
                    db.UpdateableRowLock(cacheLine).UpdateColumns(x => new { x.InStock, x.LocationNo, x.EditTime }).ExecuteCommand();
                }
            });

            #endregion 计算当前缓存线是否已全部分配任务

            WCS_TaskInfo task = null;
            short nextAdd = 0;
            int isSideNum = 0;
            SqlSugarHelper.Do(_db =>
            {
                var db = _db.Default;
                //先找到下一个地址对应的缓存信息
                var lineCache = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).Single(x => x.InStock == true && x.LocationNo == nextCode && x.Locations.Any(s => s.TaskId == obj.Data2.TaskNumber));
                if (lineCache == null)
                {
                    World.Log($"缓存组{obj.Entity.Code}未分配完");
                    return;
                }

                //检测实物数量与有货总数是否相等
                if (!lineCache.Put)
                {
                    var qty = lineCache.Locations.Count(x => x is { IsEmpty: false, InStock: true });
                    var devQty = _cacheDevices.FirstOrDefault(x => x.Key.Entity.Code == obj.Entity.Code).Value
                        .Count(x => x.Data2.Status.HasFlag(StationStatus.PH_Status));
                    if (qty != devQty && devQty < qty)
                    {
                        World.Log($"缓存组{obj.Entity.Code}工字轮未到齐");
                        return;
                    }

                    lineCache.Put = true;
                    db.UpdateableRowLock(lineCache).UpdateColumns(x => new { x.Put }).ExecuteCommand();

                    //TODO:此处不绑定码垛信息的行
                }

                var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber && v.Status == Entity.TaskStatus.FinishOfShunt) ?? throw new KnownException("未找到对应的WCS任务", LogLevelEnum.Mid);
                var location = lineCache.Locations.First(x => x.TaskId == taskInfo.ID);
                isSideNum = location.SideNum;
                taskInfo.Status = Entity.TaskStatus.ConveyorExecution;
                taskInfo.EditWho = "WCS";
                taskInfo.EditTime = DateTime.Now;
                db.UpdateableRowLock(taskInfo).UpdateColumns(x => new { x.EditWho, x.EditTime, x.Status }).ExecuteCommand();
                taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, "桁架缓存放行");
                task = taskInfo;
                nextAdd = obj.Entity.Targets.FirstOrDefault().Code.ToShort();
            });
            if (task == null) return;
            obj.Data.TaskNumber = obj.Data2.TaskNumber;
            obj.Data.TaskNumber = obj.Data2.TaskNumber;
            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
            obj.Data.GoodsEnd = nextAdd;
            obj.Data.GoodsEnd = nextAdd;
            if (isSideNum == 2)
            {
                obj.Data.CmdType = StationCmd.Res6;
                obj.Data.CmdType = StationCmd.Res6;
            }

            obj.Data.SetVoucherNo();
        }

        public override bool Select(Device dev)
        {
            return dev.HasFlag(Extensions.DeviceFlags.桁架缓存放行点);
        }

        public 桁架缓存放行点()
        {
            if (WorkStart.WareHouses.Contains("FJ1"))
            {
                //库一北
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "466"), World), Device.All.Where(x => x.Code is "466" or "467" or "468" or "469" or "470").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "480"), World), Device.All.Where(x => x.Code is "480" or "481" or "482" or "483" or "484").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "494"), World), Device.All.Where(x => x.Code is "494" or "495" or "496" or "497" or "498").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "508"), World), Device.All.Where(x => x.Code is "508" or "509" or "510" or "511" or "512").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "522"), World), Device.All.Where(x => x.Code is "522" or "523" or "524" or "525" or "526").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "536"), World), Device.All.Where(x => x.Code is "536" or "537" or "538" or "539" or "540").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "550"), World), Device.All.Where(x => x.Code is "550" or "551" or "552" or "553" or "554").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "564"), World), Device.All.Where(x => x.Code is "564" or "565" or "566" or "567" or "568").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "578"), World), Device.All.Where(x => x.Code is "578" or "579" or "580" or "581" or "582").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "591"), World), Device.All.Where(x => x.Code is "591" or "592" or "593" or "594" or "595").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                //库一南
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "666"), World), Device.All.Where(x => x.Code is "666" or "667" or "668" or "669" or "670").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "680"), World), Device.All.Where(x => x.Code is "680" or "681" or "682" or "683" or "684").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "694"), World), Device.All.Where(x => x.Code is "694" or "695" or "696" or "697" or "698").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "708"), World), Device.All.Where(x => x.Code is "708" or "709" or "710" or "711" or "712").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "722"), World), Device.All.Where(x => x.Code is "722" or "723" or "724" or "725" or "726").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "736"), World), Device.All.Where(x => x.Code is "736" or "737" or "738" or "739" or "740").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "750"), World), Device.All.Where(x => x.Code is "750" or "751" or "752" or "753" or "754").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "764"), World), Device.All.Where(x => x.Code is "764" or "765" or "766" or "767" or "768").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "778"), World), Device.All.Where(x => x.Code is "778" or "779" or "780" or "781" or "782").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "791"), World), Device.All.Where(x => x.Code is "791" or "792" or "793" or "794" or "795").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            }
            if (WorkStart.WareHouses.Contains("FJ2"))
            {
                //库二北
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "866"), World), Device.All.Where(x => x.Code is "866" or "867" or "868" or "869" or "870").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "880"), World), Device.All.Where(x => x.Code is "880" or "881" or "882" or "883" or "884").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "894"), World), Device.All.Where(x => x.Code is "894" or "895" or "896" or "897" or "898").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "908"), World), Device.All.Where(x => x.Code is "908" or "909" or "910" or "911" or "912").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "922"), World), Device.All.Where(x => x.Code is "922" or "923" or "924" or "925" or "926").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "936"), World), Device.All.Where(x => x.Code is "936" or "937" or "938" or "939" or "940").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "950"), World), Device.All.Where(x => x.Code is "950" or "951" or "952" or "953" or "954").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "964"), World), Device.All.Where(x => x.Code is "964" or "965" or "966" or "967" or "968").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "978"), World), Device.All.Where(x => x.Code is "978" or "979" or "980" or "981" or "982").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "991"), World), Device.All.Where(x => x.Code is "991" or "992" or "993" or "994" or "995").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                //库二南
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1066"), World), Device.All.Where(x => x.Code is "1066" or "1067" or "1068" or "1069" or "1070").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1080"), World), Device.All.Where(x => x.Code is "1080" or "1081" or "1082" or "1083" or "1084").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1094"), World), Device.All.Where(x => x.Code is "1094" or "1095" or "1096" or "1097" or "1098").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1108"), World), Device.All.Where(x => x.Code is "1108" or "1109" or "1110" or "1111" or "1112").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1122"), World), Device.All.Where(x => x.Code is "1122" or "1123" or "1124" or "1125" or "1126").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1136"), World), Device.All.Where(x => x.Code is "1136" or "1137" or "1138" or "1139" or "1140").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1150"), World), Device.All.Where(x => x.Code is "1150" or "1151" or "1152" or "1153" or "1154").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1164"), World), Device.All.Where(x => x.Code is "1164" or "1165" or "1166" or "1167" or "1168").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1178"), World), Device.All.Where(x => x.Code is "1178" or "1179" or "1180" or "1181" or "1182").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1191"), World), Device.All.Where(x => x.Code is "1191" or "1192" or "1193" or "1194" or "1195").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            }
            if (WorkStart.WareHouses.Contains("FJ3"))
            {
                //库三北
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1266"), World), Device.All.Where(x => x.Code is "1266" or "1267" or "1268" or "1269" or "1270").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1280"), World), Device.All.Where(x => x.Code is "1280" or "1281" or "1282" or "1283" or "1284").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1294"), World), Device.All.Where(x => x.Code is "1294" or "1295" or "1296" or "1297" or "1298").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1308"), World), Device.All.Where(x => x.Code is "1308" or "1309" or "1310" or "1311" or "1312").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1322"), World), Device.All.Where(x => x.Code is "1322" or "1323" or "1324" or "1325" or "1326").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1336"), World), Device.All.Where(x => x.Code is "1336" or "1337" or "1338" or "1339" or "1340").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1350"), World), Device.All.Where(x => x.Code is "1350" or "1351" or "1352" or "1353" or "1354").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1364"), World), Device.All.Where(x => x.Code is "1364" or "1365" or "1366" or "1367" or "1368").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1378"), World), Device.All.Where(x => x.Code is "1378" or "1379" or "1380" or "1381" or "1382").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1391"), World), Device.All.Where(x => x.Code is "1391" or "1392" or "1393" or "1394" or "1395").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                //库三南
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1466"), World), Device.All.Where(x => x.Code is "1466" or "1467" or "1468" or "1469" or "1470").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1480"), World), Device.All.Where(x => x.Code is "1480" or "1481" or "1482" or "1483" or "1484").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1494"), World), Device.All.Where(x => x.Code is "1494" or "1495" or "1496" or "1497" or "1498").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1508"), World), Device.All.Where(x => x.Code is "1508" or "1509" or "1510" or "1511" or "1512").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1522"), World), Device.All.Where(x => x.Code is "1522" or "1523" or "1524" or "1525" or "1526").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1536"), World), Device.All.Where(x => x.Code is "1536" or "1537" or "1538" or "1539" or "1540").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1550"), World), Device.All.Where(x => x.Code is "1550" or "1551" or "1552" or "1553" or "1554").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1564"), World), Device.All.Where(x => x.Code is "1564" or "1565" or "1566" or "1567" or "1568").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1578"), World), Device.All.Where(x => x.Code is "1578" or "1579" or "1580" or "1581" or "1582").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
                _cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "1591"), World), Device.All.Where(x => x.Code is "1591" or "1592" or "1593" or "1594" or "1595").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            }
        }
    }
}