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;

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

        protected override bool SaveLogsToFile => 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) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
            if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
            if (obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
            if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
            if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
            var nextDev = new Device<IStation524, IStation523>(obj.Entity.Targets.FirstOrDefault()!, World);
            if (nextDev.Data2.Status1.HasFlag(StationStatus1.IsLock)) throw new KnownException($"{nextDev.Entity.Code}桁架未取货完成，线体锁定中", LogLevelEnum.Mid);

            //获取当前缓存线信息对应设备号的下一个地址
            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 }))
                {
                    //判断下一个地址当前是否有对应的任务
                    if (db.Queryable<WCS_CacheLine>().Any(x => x.LocationNo == nextCode && x.IsTruss == false)) return;
                    //没有对应的任务，开始释放缓存
                    cacheLine.InStock = true;
                    cacheLine.LocationNo = devCode.Code.ToShort();
                    cacheLine.EditTime = DateTime.Now;
                    db.Updateable(cacheLine).ExecuteCommand();
                }
            });

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

            WCS_TaskInfo task = null;
            SqlSugarHelper.Do(_db =>
            {
                var db = _db.Default;
                //先找到下一个地址对应的缓存信息
                var lineCache = db.Queryable<WCS_CacheLine>().Includes(x => x.Locations).Single(x => x.LocationNo == nextCode && x.Locations.Any(s => s.TaskId == obj.Data2.TaskNumber));
                if (lineCache == null) 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) return; //表示当前货物未全部到位
                    lineCache.Put = true;
                    db.Updateable(lineCache).ExecuteCommand();

                    var pr = db.Queryable<WCS_PalletizingRow>().Single(x => x.Id == lineCache.PalletizingRowId);
                    pr.LineCode = lineCache.LocationNo.ToString();
                    db.Updateable(pr).ExecuteCommand();
                }

                var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber && v.Status == Entity.TaskStatus.FinishOfShunt) ?? throw new KnownException("未找到对应的WCS任务", LogLevelEnum.Mid);
                taskInfo.Status = Entity.TaskStatus.ConveyorExecution;
                taskInfo.AddrNext = obj.Entity.Targets.FirstOrDefault().Code;
                taskInfo.EditWho = "WCS";
                taskInfo.EditTime = DateTime.Now;
                db.Updateable(taskInfo).ExecuteCommand();
                taskInfo.AddWCS_TASK_DTL(db, obj.Entity.Code, taskInfo.AddrNext, "桁架缓存放行");
                task = taskInfo;
            });
            if (task == null) return;
            obj.Data.TaskNumber = obj.Data2.TaskNumber;
            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
            obj.Data.GoodsEnd = task.AddrNext.ToShort();
            obj.Data.VoucherNo++;
        }

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

        public 桁架缓存放行点()
        {
            _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 "481" or "482" or "483" or "484" or "480").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 == "545"), World), Device.All.Where(x => x.Code is "546" or "547" or "548" or "549" or "545").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            //_cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "559"), World), Device.All.Where(x => x.Code is "559" or "560" or "561" or "562" or "563").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            //_cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "573"), World), Device.All.Where(x => x.Code is "573" or "574" or "575" or "576" or "577").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
            //_cacheDevices.Add(new Device<IStation524, IStation523>(Device.All.First(x => x.Code == "586"), World), Device.All.Where(x => x.Code is "586" or "587" or "588" or "589" or "590").Select(x => new Device<IStation524, IStation523>(x, World)).ToList());
        }
    }
}
