using PlcSiemens.Core.Extension;
using ServiceCenter.Logs;
using ServiceCenter.SqlSugars;
using System.ComponentModel;
using WCS.Core;
using WCS.Entity;
using WCS.Entity.Protocol.SRM;
using WCS.Entity.Protocol.Station;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.WebApi.Controllers;
using WCS.WorkEngineering.Worlds;
using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
using TaskStatus = WCS.Entity.TaskStatus;

namespace WCS.WorkEngineering.Systems
{
    /// <summary>
    ///  Agv交互系统
    /// </summary>
    [BelongTo(typeof(MainWorld))]
    [Description("Agv交互系统")]
    public class AgvSystems : DeviceSystem<Device<IStation520>>
    {
        protected override bool ParallelDo => true;

        protected override bool SaveLogsToFile => true;

        private List<Station> devs = new List<Station>();
        private List<SRM> srms = new List<SRM>();

        public AgvSystems()
        {
            devs = Device.All.Where(v => v.HasFlag(DeviceFlags.入库, DeviceFlags.巷道口)).Select(v => new Station(v, this.World)).ToList();
            srms = Device.All.Where(v => v.HasProtocol(typeof(ISRM520))).Select(v => new SRM(v, this.World)).ToList();
        }

        public override void Do(Device<IStation520> obj)
        {
            if (obj.Entity.Code == "出库AGV")
            {
                var agvTaskInfos = new List<WCS_AgvTaskInfo>();
                //获取所有未结束的叫料及背负式补空AGV任务
                SqlSugarHelper.Do(db =>
                {
                    agvTaskInfos = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.TaskType == AGVTaskType.CallMaterial)
                                                                         .Where(v => v.Status < AGVTaskStatus.MissionCompleted)
                                                                         .SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.AddTime).ToList();
                });
                //有需要处理的AGV任务
                if (agvTaskInfos.Any())
                {
                    this.ExRecord(obj.Entity.Code, "可用出库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList());
                    var taskInfos = new List<WCS_TaskInfo>();

                    foreach (var agv in agvTaskInfos)
                    {
                        try
                        {
                            SqlSugarHelper.Do(db =>
                            {
                                switch (agv.AgvStatus)
                                {
                                    //取货点安全交互
                                    case AGVTaskStatus.RequestOrPermission2 when agv.Status != AGVTaskStatus.RequestOrPermission2:
                                        {
                                            var taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == agv.TaskId);
                                            agv.Status = AGVTaskStatus.RequestOrPermission2;
                                            db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                            taskInfo.AddWCS_TASK_DTL(db.Default, "agv", $"允许AGV任务{agv.ID}在站台{agv.Station}取货");
                                            AgvApi.ContinueTask(agv.AgvID, agv.Station);
                                            break;
                                        }
                                    case AGVTaskStatus.PutRequestOrPermission when agv.Status != AGVTaskStatus.PutRequestOrPermission:
                                        {
                                            agv.Status = AGVTaskStatus.PutRequestOrPermission;
                                            db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                            AgvApi.ContinueTask(agv.AgvID, agv.Station);
                                            break;
                                        }
                                    case AGVTaskStatus.LeaveGet when agv.Status != AGVTaskStatus.LeaveGet:
                                        var devinfo = new Device<IStation520, IStation521>(Device.All.First(x => x.Code == agv.Position), World);
                                        devinfo.Data.CmdType = StationCmd.Res3;
                                        agv.Status = AGVTaskStatus.LeaveGet;
                                        db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                        break;
                                    //完成任务
                                    case AGVTaskStatus.MissionCompleted when agv.Status != AGVTaskStatus.MissionCompleted:
                                        {
                                            if (agv.TaskType is AGVTaskType.CallForMaterial or AGVTaskType.ForkliftFilling or AGVTaskType.CallMaterial)
                                            {
                                                var taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agv.ID);
                                                if (taskInfo == null) throw new Exception($"未找到AGV任务{agv.ID}对应WCS任务");
                                                //更新AGV任务状态
                                                agv.Status = AGVTaskStatus.MissionCompleted;
                                                db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                                //更新WCS任务状态
                                                taskInfo.Status = Entity.TaskStatus.Finish;
                                                taskInfo.EndTime = DateTime.Now;
                                                db.Default.Updateable(taskInfo).ExecuteCommand();
                                                taskInfo.AddWCS_TASK_DTL(db.Default, "agv", "任务完成");
                                                taskInfos.Add(taskInfo);
                                            }
                                            else
                                            {
                                                agv.Status = AGVTaskStatus.MissionCompleted;
                                                db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                            }

                                            break;
                                        }
                                }
                            });
                        }
                        catch (Exception ex)
                        {
                            World.Log(ex.Message, LogLevelEnum.Mid);
                            this.ExRecord(obj.Entity.Code, ex.Message);
                        }
                    }

                    foreach (var taskInfo in taskInfos.Where(taskInfo => taskInfo.Status == TaskStatus.Finish))
                    {
                        WmsApi.CompleteTask(taskInfo.ID);
                    }
                }
            }
            else if (obj.Entity.Code == "入库AGV")
            {
                List<WCS_AgvTaskInfo> agvTaskInfos = new List<WCS_AgvTaskInfo>();
                //获取所有未结束的入库AGV任务
                SqlSugarHelper.Do(db =>
                {
                    agvTaskInfos = db.Default.Queryable<WCS_AgvTaskInfo>()
                                             .Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot)
                                             .SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.EditTime).ToList();
                });

                if (agvTaskInfos.Any())
                {
                    this.ExRecord(obj.Entity.Code, "可用入库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList());
                    foreach (var agv in agvTaskInfos)
                    {
                        try
                        {
                            SqlSugarHelper.Do(db =>
                            {
                                #region 开始跟据AGV状态做出处理

                                switch (agv.AgvStatus)
                                {
                                    case AGVTaskStatus.NewBuild when agv.Status == AGVTaskStatus.NewBuild:
                                        AgvApi.托盘回库(agv.Position, agv.ID.ToString());
                                        agv.AgvID = agv.ID.ToString();
                                        agv.Status = AGVTaskStatus.Confirm;
                                        agv.AgvStatus = AGVTaskStatus.Confirm;
                                        db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                        break;
                                    //巷道分配
                                    case AGVTaskStatus.RequestOrPermission1 when agv.Status != AGVTaskStatus.Complete1:
                                        {
                                            agv.Status = AGVTaskStatus.Complete1;
                                            agv.Position = "2501";
                                            db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();

                                            //task.Status = TaskStatus.Finish;
                                            //db.Default.Updateable(task).ExecuteCommand();
                                            //task.AddWCS_TASK_DTL(db.Default, "AGV搬运任务分配放货点", agv.Position, $"任务分配至:{agv.Position}");
                                            //调继续执行任务接口
                                            AgvApi.ContinueTask(agv.AgvID, agv.Position);
                                            //}
                                            break;
                                        }
                                    //取货站点安全交互
                                    case AGVTaskStatus.RequestOrPermission2 when agv.Status != AGVTaskStatus.RequestOrPermission2:
                                        {
                                            if (agv.Position.IsNullOrEmpty()) throw new Exception($"无有效放货地址");
                                            var dev = Device.All.First(x => x.Code == agv.Position);
                                            //调继续执行任务接口
                                            AgvApi.ContinueTask(agv.AgvID, dev.Code);
                                            break;
                                        }
                                    case AGVTaskStatus.LeaveGet when agv.Status != AGVTaskStatus.LeaveGet:
                                        var devinfo = new Device<IStation520, IStation521>(Device.All.First(x => x.Code == agv.Position), World);
                                        devinfo.Data.CmdType = StationCmd.Res3;
                                        break;
                                    //完成任务
                                    case AGVTaskStatus.MissionCompleted when agv.Status != AGVTaskStatus.MissionCompleted:
                                        if (agv.TaskType == AGVTaskType.EnterDepot)
                                        {
                                            agv.Status = AGVTaskStatus.MissionCompleted;
                                            db.Default.Updateable(agv).SplitTable(x=>x.Take(2)).ExecuteCommand();
                                        }
                                        break;
                                }

                                #endregion 开始跟据AGV状态做出处理
                            });
                        }
                        catch (Exception ex)
                        {
                            World.Log(ex.Message, LogLevelEnum.Mid);
                            this.ExRecord(obj.Entity.Code, ex.Message);
                        }
                    }
                }
            }
        }

        public override bool Select(Device dev)
        {
            return dev.Code is "出库AGV" or "入库AGV";
        }
    }
}
