using ServiceCenter.Extensions;
using ServiceCenter.Logs;
using ServiceCenter.SqlSugars;
using System.ComponentModel;
using WCS.Core;
using WCS.Entity;
using WCS.Entity.Protocol.BCR;
using WCS.Entity.Protocol.RGV;
using WCS.Entity.Protocol.Robot;
using WCS.Entity.Protocol.Station;
using WCS.Entity.Protocol.Truss;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.Worlds;
using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
using TaskStatus = WCS.Entity.TaskStatus;

namespace WCS.WorkEngineering.Systems
{
    /// <summary>
    ///  Agv交互系统
    /// </summary>
    [BelongTo(typeof(RgvWorld))]
    [Description("RGV交互系统")]
    public class RGVSystems : DeviceSystem<Device<IRGV520, IRGV521, IBCR81>>
    {
        protected override bool ParallelDo => true;

        protected override bool SaveLogsToFile => true;

        /// <summary>
        /// 取货点设备集合
        /// </summary>
        private readonly Dictionary<string, List<Device<IStation520, IStation521, IStation523>>> _pickUpDevices = new();

        public RGVSystems()
        {
            //获取所有的巷道集合
            var rgvList = Device.All.Where(v => v.HasFlag(DeviceFlags.RGV));
            foreach (var rgv in rgvList)
            {
                _pickUpDevices.Add(rgv.Code, rgv.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523>(v, this.World)).ToList());
            }
        }

        public override void Do(Device<IRGV520, IRGV521, IBCR81> obj)
        {
            //var dev1 = new Device<IStation520>(Device.All.First(x => x.Code == "1602"), World);
            //dev1.Data.TaskNumber = 0;
            //dev1.Data.GoodsEnd=0;

            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
            if (obj.Data2.WorkMode != RGVWorkMode.Automatic) return;

            if (obj.Data.RES1 == 1) return; //wcs任务完成确认信号未清除

            if (obj.Data2.Status.HasFlag(RGVStatus.Taskfinishi))
            {
                switch (obj.Data2.CmdType)
                {
                    case RGVCmdType.PickGoods: //单独取货任务完成,默认只有空托盘才会下发单独取货任务
                        //开始申请读码信息
                        var bcrCode = obj.Data3.GetBCRCode();
                        int taskNumber = 0;
                        SqlSugarHelper.Do(_db =>
                        {
                            var db = _db.Default;
                            var dev = Device.All.First(x => x.Code == obj.Data2.StartPosition.ToString());
                            if (dev.HasFlag(DeviceFlags.拆盘机09))
                            {
                                //开始绑定任务，并下发新的任务信息到小车
                                WCS_Palletizing palletizingInfo = db.Queryable<WCS_Palletizing>().Single(x => x.Id == obj.Data2.TaskNumber);
                                if (palletizingInfo == null) return;
                                palletizingInfo.PalleCode = bcrCode;
                                db.Updateable(palletizingInfo).ExecuteCommand();
                                taskNumber = palletizingInfo.Id;
                            }
                            else if (dev.HasFlag(DeviceFlags.拆盘机非09))
                            {
                                //开始处理对应的搬运任务信息
                                var task = db.Queryable<WCS_TaskInfo>().First(x => x.Type == TaskType.Delivery && x.ID == obj.Data2.TaskNumber && x.AddrTo == obj.Data2.DestPosition.ToString());
                                if (task == null) throw new KnownException($"未找到对应的任务{obj.Data2.TaskNumber}", LogLevelEnum.Mid);
                                task.BarCode = bcrCode;
                                db.Updateable(task).ExecuteCommand();
                                task.AddWCS_TASK_DTL(db, obj.Entity.Code, obj.Data2.DestPosition.ToString(), $"环形库码垛位{obj.Data2.DestPosition}搬运任务绑定条码信息{bcrCode}");
                                taskNumber = task.ID;
                            }
                        });
                        if (taskNumber == 0) return;
                        //清空起始点信息
                        var staDev = new Device<IStation520>(Device.All.FirstOrDefault(x => x.Code == obj.Data2.DestPosition.ToString())!, World);
                        staDev.Data.TaskNumber = 0;
                        staDev.Data.GoodsStart = 0;
                        staDev.Data.GoodsEnd = 0;
                        obj.Data2.TaskNumber = taskNumber;
                        obj.Data.RES1 = 1;
                        break;

                    case RGVCmdType.PutGoods:
                        WCS_TaskInfo finishiTask = null;
                        var startPosition = Device.All.Where(x => x.Code == obj.Data2.StartPosition.ToString()).Select(x => new Device<IStation520, IStation521, IStation523>(x, World)).FirstOrDefault();
                        var destPosition = Device.All.FirstOrDefault(x => x.Code == obj.Data2.DestPosition.ToString());
                        var isPalletizing = destPosition!.HasFlag(DeviceFlags.桁架码垛位, DeviceFlags.环形库码垛工位);
                        short countQty = 0;
                        short shortCode = 0;
                        SqlSugarHelper.Do(_db =>
                        {
                            var db = _db.Default;
                            if (isPalletizing)
                            {
                                if (destPosition.HasFlag(DeviceFlags.桁架码垛位))
                                {
                                    var palletizingInfo = db.Queryable<WCS_Palletizing>().First(x => x.Id == obj.Data.TaskNumber);
                                    countQty = palletizingInfo.CountQty.ToShort();
                                    shortCode = palletizingInfo.ShortCode;
                                }
                                else if (destPosition.HasFlag(DeviceFlags.环形库码垛工位))
                                {
                                    var deliveryTask = db.Queryable<WCS_TaskInfo>().First(x => x.ID == obj.Data.TaskNumber);
                                    countQty = deliveryTask.FullQty;
                                    shortCode = deliveryTask.PalletType;
                                    deliveryTask.Status = TaskStatus.RgvCompleted;
                                    deliveryTask.EditTime = DateTime.Now;
                                    deliveryTask.LastInteractionPoint = obj.Entity.Code;
                                    db.Updateable(deliveryTask).ExecuteCommand();
                                    deliveryTask.AddWCS_TASK_DTL(db, deliveryTask.AddrTo, $"RGV任务执行结束");
                                }
                            }
                        });

                        //初始化起始点信息
                        startPosition.Data.TaskNumber = 0;
                        startPosition.Data.GoodsEnd = 0;
                        //目标地址是码垛工位
                        if (isPalletizing)
                        {
                            if (destPosition.HasFlag(DeviceFlags.桁架码垛位))
                            {
                                var dest = new Device<ITruss530>(destPosition!, World);
                                dest.Data.MaxQuantity = countQty;
                                dest.Data.Type = shortCode;
                                dest.Data.VoucherNo++;
                            }
                            else if (destPosition.HasFlag(DeviceFlags.环形库码垛工位))
                            {
                                var dest = new Device<IRobot530>(destPosition!, World);
                                dest.Data.MaxQuantity = countQty;
                                dest.Data.Type = shortCode;
                                dest.Data.VoucherNo++;
                            }
                        }
                        obj.Data.RES1 = 1;
                        break;

                    case RGVCmdType.Move:
                        obj.Data.RES1 = 1;
                        break;

                    case RGVCmdType.ChangePutGoods:
                        break;

                    case RGVCmdType.ChangePickGoods:
                        break;

                    case RGVCmdType.PickPutGoods:
                        staDev = new Device<IStation520, IStation521>(Device.All.FirstOrDefault(x => x.Code == obj.Data.DestPosition.ToString())!, World);
                        staDev.Data.TaskNumber = 0;
                        staDev.Data.GoodsStart = 0;
                        staDev.Data.GoodsEnd = 0;
                        obj.Data.RES1 = 1;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                }
                return;
            }

            if (obj.Data2.SystemStatus != RGVSystemStatus.空闲) return;

            if (obj.Data2.Status.HasFlag(RGVStatus.RES1))
            {
                obj.Data.TaskNumber = obj.Data.TaskNumber;
                obj.Data.CmdType = RGVCmdType.Move;
                obj.Data.DestPosition = 1668;
                obj.Data.VoucherNo++;
                return;
            }

            if (obj.Data2.CmdType == RGVCmdType.PickGoods && !obj.Data2.Status.HasFlag(RGVStatus.Taskfinishi))
            {
                if (obj.Data2.Status.HasFlag(RGVStatus.PH_Status))
                {
                    obj.Data.TaskNumber = obj.Data.TaskNumber;
                    obj.Data.CmdType = RGVCmdType.PutGoods;
                    obj.Data.StartPosition = obj.Data2.StartPosition;
                    obj.Data.DestPosition = obj.Data2.DestPosition;
                    obj.Data.VoucherNo++;
                    return;
                }
            }
            var pickUpDevices = _pickUpDevices.FirstOrDefault(x => x.Key == obj.Entity.Code).Value;

            //有货且需要搬运货物的站台
            var devs = pickUpDevices.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status) && v.Data.TaskNumber != 0)
                                                  .Where(v => v.Entity.Code.ToShort() != v.Data.GoodsEnd && v.Data.GoodsEnd != 0)
                                                  .ToList();
            //筛选出目标站台无货的站台
            var putDev = obj.Entity.Targets.Where(x => x.HasFlag(DeviceFlags.输送机))
                .Select(x => new Device<IStation520, IStation521, IStation523>(x, World))
                .Where(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status))
                .Select(x => x.Entity.Code.ToShort());
            var dev = devs.OrderBy(x => x.Entity.Code).FirstOrDefault(x => putDev.Contains(x.Data.GoodsEnd));
            if (dev == null) return;
            //区分任务是拆盘机到码垛工位，还是码垛工位到拆盘机
            if (dev.Entity.HasFlag(DeviceFlags.拆盘机09, DeviceFlags.拆盘机非09))
            {
                obj.Data.TaskNumber = dev.Data.TaskNumber;
                obj.Data.CmdType = RGVCmdType.PickGoods;
                obj.Data.StartPosition = dev.Entity.Code.ToShort();
                obj.Data.DestPosition = dev.Data.GoodsEnd;
                obj.Data.VoucherNo++;
            }
            else //非拆盘机起始任务
            {
                //站台中的任务号
                WCS_TaskInfo task = null;
                SqlSugarHelper.Do(_db =>
                {
                    var db = _db.Default;
                    var taskInfo = db.Queryable<WCS_TaskInfo>().First(p => p.ID == dev.Data.TaskNumber && p.Status == TaskStatus.WaitingToExecute);
                    if (taskInfo == null) return;
                    taskInfo.Status = TaskStatus.RgvExecution;
                    taskInfo.AddrNext = obj.Entity.Code;
                    taskInfo.EditWho = "WCS";
                    taskInfo.EditTime = DateTime.Now; ;
                    db.Updateable(taskInfo).ExecuteCommand();
                    taskInfo.AddWCS_TASK_DTL(db, dev.Entity.Code, obj.Entity.Code, $"任务分配至{obj.Entity.Code}");
                    task = taskInfo;
                });
                if (task == null) return;
                obj.Data.TaskNumber = task.ID;
                obj.Data.CmdType = RGVCmdType.PickPutGoods;
                obj.Data.StartPosition = dev.Entity.Code.ToShort();
                obj.Data.DestPosition = dev.Data.GoodsEnd;
                obj.Data.VoucherNo++;
            }
        }

        public override bool Select(Device dev)
        {
            return dev.Code == "RGV1";
            //return dev.HasFlag(Extensions.DeviceFlags.RGV);
        }
    }
}
