using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using PlcSiemens.Core.Extension;
using ServiceCenter;
using ServiceCenter.SqlSugars;
using System.Net.Http.Json;
using WCS.Core;
using WCS.Entity;
using WCS.Entity.Protocol.Station;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.Systems;
using WCS.WorkEngineering.WebApi.Models.AGV;
using WCS.WorkEngineering.WebApi.Models.AGV.Request;
using WCS.WorkEngineering.WebApi.Models.AGV.Response;

namespace WCS.WorkEngineering.WebApi.Controllers
{
    /// <summary>
    /// AGV相关接口控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class AgvController : ControllerBase
    {
        /// <summary>
        ///  AGV任务下发测试
        /// </summary>
        /// <param name="type">任务类型</param>
        /// <param name="code">RFID</param>
        /// <param name="pos">目标位置</param>
        /// <returns></returns>
        [HttpPost]
        public string AgvDebug(int type, string code, string pos)
        {
            try
            {
                switch (type)
                {
                    case 1:
                        AgvApi.机台补空(pos, code, "1");
                        break;

                    case 2:
                        //AgvApi.机台补满();
                        break;

                    case 3:
                        AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
                        break;

                    default:
                        break;
                }
                return "成功";
            }
            catch (Exception ex)
            {
                return $"Error-----" +
                      $"{ex.Message}------" +
                      $"{ex.StackTrace}";
            }
        }

        /// <summary>
        ///  背负式agv请求出库任务
        /// </summary>
        /// <param name="reqDto">请求参数</param>
        /// <returns></returns>
        [HttpPost]
        public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
        {
            lock (LockHub.ApplyEmptySpoolLock)
            {
                LogHub.InterfaceProcessLog("ApplyEmptySpool", JsonConvert.SerializeObject(reqDto));
                ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();

                try
                {
                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
                    if (!World.IsStart)
                    {
                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
                        agvFill.ResMsg = "WCS初始化中";
                        return agvFill;
                    }
                    var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;

                    // 检测三个站台是否有货
                    obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
                    if (!obj.Any())
                    {
                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
                        agvFill.ResMsg = "无空轮";
                        return agvFill;
                    }
                    SqlSugarHelper.Do(db =>
                    {
                        var res = WmsApi.GetTunnelEmptyConCount();

                        var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
                                          .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
                        obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
                        if (!obj.Any())
                        {
                            agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
                            agvFill.ResMsg = "无可用取货站点";
                            return;
                        }

                        foreach (var item in res.ResDataList)
                        {
                            var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
                                                    .Select(v => v.Targets).SelectMany(v => v)
                                                    .Where(v => v.HasProtocol(typeof(IStation520)))
                                                    .Where(v => v.Code is "1012" or "1014" or "1016")
                                                    .FirstOrDefault();
                            item.Tunnel = station.ToInt();
                        }
                        var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
                        var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
                        var id = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(v => v.Take(1)).Max(v => v.ID);
                        var agv = new WCS_AgvTaskInfo()
                        {
                            ID = db.GetAGVTaskId(),
                            TaskType = AGVTaskType.CallForMaterial,
                            Status = AGVTaskStatus.NewBuild,
                            Station = agvFill.LocCode,
                            AddWho = "WCS"
                        };
                        //创建对应的AGV任务
                        db.Default.Insertable(agv).SplitTable().ExecuteCommand();
                        var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
                        task.AgvTaskID = agv.ID;
                        db.Default.Updateable(task).ExecuteCommand();

                        agvFill.LocCode = dev.Entity.Code;
                        agvFill.SpoolType = "4";
                        agvFill.ResMsg = "";
                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
                    });
                }
                catch (Exception ex)
                {
                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
                    agvFill.ResMsg = ex.Message;
                }
                LogHub.InterfaceProcessLog("ApplyEmptySpool", JsonConvert.SerializeObject(agvFill));
                return agvFill;
            }
        }

        /// <summary>
        /// AGV执行回调
        /// </summary>
        /// <param name="reqDto"></param>
        /// <returns></returns>
        [HttpPost]
        public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
        {
            lock (LockHub.AgvCallbackLock)
            {
                LogHub.InterfaceProcessLog("AgvCallback", JsonConvert.SerializeObject(reqDto));
                var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
                WCS_TaskInfo taskInfo = null;
                try
                {
                    SqlSugarHelper.Do(db =>
                    {
                        //跟据AGVid找到对应的AGV任务
                        var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted);
                        if (agvTask == null && reqDto.method != "applySecurity")
                        {
                            res.code = AgvResponseCode.Fail;
                            res.message = "未找到对应的AGV任务";
                            return;
                        }
                        switch (reqDto.method)
                        {
                            //case "start": //表示请求巷道
                            //    agvTask.Status = AGVTaskStatus.RequestOrPermission1;
                            //    break;

                            //case "end": //表示请求巷道
                            //    agvTask.Status = AGVTaskStatus.RequestOrPermission1;
                            //    break;

                            case "applyContinue": //表示请求巷道

                                agvTask.Status = AGVTaskStatus.RequestOrPermission1;
                                break;

                            case "applySecurity": //表示请求放货或取货
                                if (reqDto.callCode is "1012" or "1014" or "1016")
                                {
                                    agvTask = db.Default.Queryable<WCS_AgvTaskInfo>()
                                                        .SplitTable(tabs => tabs.Take(2))
                                                        .First(v => v.Status == AGVTaskStatus.NewBuild && v.TaskType == AGVTaskType.CallForMaterial && v.Station == reqDto.callCode)
                                                        ?? throw new Exception("为找找到对应AGV任务");
                                    agvTask.AgvID = reqDto.taskCode;
                                    var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
                                    var id = obj.FirstOrDefault(v => v.Entity.Code == agvTask.Station).Data.TaskNumber;
                                    taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == id) ?? throw new Exception("为找找到对应WCS任务");
                                    taskInfo.AgvTaskID = agvTask.ID;
                                    taskInfo.Status = Entity.TaskStatus.AGVExecution;
                                    db.Default.Updateable(taskInfo).ExecuteCommand();
                                    taskInfo.AddWCS_TASK_DTL(db, agvTask.Station, "agv执行中");
                                }
                                if (agvTask == null)
                                {
                                    res.code = AgvResponseCode.Fail;
                                    res.message = "未找到对应的AGV任务";
                                    return;
                                }
                                agvTask.Status = AGVTaskStatus.RequestOrPermission2;
                                break;

                            case "hjend_2": //补空任务完成
                                if (agvTask.TaskType == AGVTaskType.CallForMaterial)
                                {
                                    taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agvTask.ID) ?? throw new Exception("为找找到对应WCS任务");
                                    taskInfo.Status = Entity.TaskStatus.Finish;
                                    taskInfo.EedTime = DateTime.Now;
                                    taskInfo.AddWCS_TASK_DTL(db, "agv缓存区", "任务完成");
                                    db.Default.Updateable(taskInfo).ExecuteCommand();
                                    taskInfo.CompleteOrCancelTasks(db);
                                }
                                agvTask.Status = AGVTaskStatus.MissionCompleted;
                                break;

                            case "endhjBM": //取满任务完成
                                agvTask.Status = AGVTaskStatus.MissionCompleted;
                                break;

                            case "end": //二楼出满任务完成s
                                agvTask.Status = AGVTaskStatus.MissionCompleted;
                                taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agvTask.ID) ?? throw new Exception("为找找到对应WCS任务");
                                taskInfo.Status = Entity.TaskStatus.Finish;
                                taskInfo.AddWCS_TASK_DTL(db, "agv", "任务完成");
                                db.Default.Updateable(taskInfo).ExecuteCommand();
                                taskInfo.CompleteOrCancelTasks(db);
                                break;

                            case "tcEnd": //机台补空任务完成
                                agvTask.Status = AGVTaskStatus.MissionCompleted;
                                taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agvTask.ID) ?? throw new Exception("为找找到对应WCS任务");
                                taskInfo.Status = Entity.TaskStatus.Finish;
                                taskInfo.AddWCS_TASK_DTL(db, "agv", "任务完成");
                                db.Default.Updateable(taskInfo).ExecuteCommand();
                                taskInfo.CompleteOrCancelTasks(db);
                                break;

                            case "exc_end": //异常信息上抛-值不匹配
                                agvTask.Status = AGVTaskStatus.MissionCompleted;
                                break;

                            case "outbin": //小车退出取货位
                                agvTask.Status = AGVTaskStatus.Complete3;
                                break;

                            default:
                                break;
                        }
                        db.Default.Updateable(agvTask).SplitTable().ExecuteCommand();
                        res.code = AgvResponseCode.Success;
                        res.message = "成功";
                    });
                    if (taskInfo != null && taskInfo.Status == Entity.TaskStatus.Finish) WmsApi.CompleteTask(taskInfo.ID);
                }
                catch (Exception ex)
                {
                    res.code = AgvResponseCode.Error;
                    res.message = ex.Message;
                }
                LogHub.InterfaceProcessLog("AgvCallback", JsonConvert.SerializeObject(res));
                return res;
            }
        }
    }
}
