using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.Common;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Share.Constant;
using Siger.Middlelayer.Share.Enum.ModuleEnum;
using static Siger.Middlelayer.Share.Enum.ModuleEnum.Automation;

namespace Siger.ApiACC.Controllers
{
    [NoTokenValidateFilter]
    public class AutomationController : LaisiBaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly IAutomationLineMode _automationLineMode;
        private readonly IAutomationMachineStatus _automationMachineStatus;
        private readonly ISigerDict _sigerDict;
        private readonly IAutomationTaskListRepository _automationTaskList;
        private readonly ISigerProjectMachineAttributionRepository _sigerProjectMachineAttribution;
        private readonly IAutomationFixtureMonitor _automationFixtureMonitor;

        public AutomationController(IUnitOfWork unitOfWork,ISigerProjectLevelSectionRepository sigerProjectLevelSection,IAutomationLineMode automationLineMode,IAutomationMachineStatus automationMachineStatus,ISigerDict sigerDict,IAutomationTaskListRepository automationTaskList,
            ISigerProjectMachineAttributionRepository sigerProjectMachineAttribution, IAutomationFixtureMonitor automationFixtureMonitor)
        {
            _unitOfWork = unitOfWork;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _automationLineMode = automationLineMode;
            _automationMachineStatus = automationMachineStatus;
            _sigerDict = sigerDict;
            _automationTaskList = automationTaskList;
            _sigerProjectMachineAttribution = sigerProjectMachineAttribution;
            _automationFixtureMonitor = automationFixtureMonitor;
        }
  
        /// <summary>
        /// 设备状态接口 用于 保存 设备当前可用状态
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult MachineStatus([FromBody]RequestAutomationMachine request)
        {
            var machineAttr = _sigerProjectMachineAttribution.Get(f => f.projectid == PID && f.machine == request.machineid);
            if (machineAttr==null)
            {
                throw new BadRequestException(ConfigEnum.MachineAttributionNotFound);
            }
            var exitsObj = _automationMachineStatus.Get(f => f.machineid == request.machineid);
            if (exitsObj==null)
            {
                _automationMachineStatus.Insert(new siger_automation_machine_status{ 
                     section=machineAttr.station,
                     machineid=request.machineid,
                     projectId=PID,
                     updatetime=DateTime.Now,
                     enable=request.enable,
                     status=request.status
                });
            }else
            {
                exitsObj.enable = request.enable;
                exitsObj.status = request.status;
                exitsObj.updatetime = DateTime.Now;
            }
           
            if (_unitOfWork.Commit() > 0)
            {
                // 设备空闲，或者完成时触发 自动任务
                if (request.enable == 1)
                {
                    if (request.status == (int)Automation.MachineStatus.Waiting || request.status == (int)Automation.MachineStatus.Complated)
                    {
                        var tasklist = _automationTaskList.GetList(f => f.projectId == PID && f.status >= (int)TaskResultStatus.Cancel && f.status < (int)TaskResultStatus.Complated);
                        if (!tasklist.Any())
                        {
                            var section = _sigerProjectLevelSection.Get(f => f.id == machineAttr.station);
                            if (section != null)
                            {
                                Logger.WriteLineInfo($"MachineStatus 设备状态 触发自动任务检查");
                                AutoProcess(section.parentid);
                            }
                        }
                    }
                }
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 产线模式  0:手动模式 /1:自动模式（产生自动任务）
        /// </summary>
        /// <param name="line"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult LineMode(int line, int mode)
        {
            var exitObj = _automationLineMode.Get(f => f.section == line);
            if (exitObj == null)
            {
                _automationLineMode.Insert(new siger_automation_line_mode
                {
                    section = line,
                    projectId = PID,
                    status = 0, 
                    updatetime = DateTime.Now,
                    mode = mode
                });
            }
            else
            {
                exitObj.updatetime = DateTime.Now;
                exitObj.mode = mode;
                _automationLineMode.Update(exitObj);
            }
        
            if (_unitOfWork.Commit() > 0)
            {
                if (mode == 1)
                {
                    //TODO
                    //手动-》自动 时
                    //task 无任务时候 ，根据设备状态创建任务
                    var tasklist = _automationTaskList.GetList(f => f.projectId == PID && f.status >= (int)TaskResultStatus.Cancel && f.status < (int)TaskResultStatus.Complated);
                    if (!tasklist.Any())
                    {
                        Logger.WriteLineInfo($"LineMode Mode=1 触发自动任务检查");
                        AutoProcess(line);
                    }
                }
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        ///  产线 需要检验
        /// </summary>
        /// <param name="line"></param>
        /// <param name="enable"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Inspect(int line, int enable)
        {
            var exitObj = _automationLineMode.Get(f => f.section == line);
            if (exitObj == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            exitObj.updatetime = DateTime.Now;
            exitObj.inspect = enable;

            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            else
                throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 任务状态接口  用于保存PLC 实时任务状态 ()
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult TaskResult([FromBody]RequestAutomationTaskResult request)
        {
            //1.检查Tasklist
            var taskObj = _automationTaskList.Get(f => f.no== request.guid);
            if (taskObj == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (taskObj.status==(int)TaskResultStatus.Complated)
            {
                throw new BadRequestException(AccEnum.AutoTaskDone);
            }
            //2.更新状态
            taskObj.status = request.status;
            _automationTaskList.Update(taskObj);

            var machineStatus = _automationMachineStatus.Get(f => f.section == taskObj.sectionid);
            if (machineStatus==null)
            {
                throw new BadRequestException(AccEnum.MachineDisable);
            }

            machineStatus.status = request.status;
            _automationMachineStatus.Update(machineStatus);

            if (_unitOfWork.Commit() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }

            //是否还有未完成任务
            var taskDone = _automationTaskList.Get(f => f.projectId == PID && f.status > (int)TaskResultStatus.Cancel && f.status < (int)TaskResultStatus.Complated);
            if(taskDone!=null)
            {
                //还有未完成任务 退出 等待任务下发
                return new ObjectResult(CommonEnum.Succefull);
            }

            //3.Tasklist 任务全部完成 ,创建自动任务
         
            switch (request.status)
            {
                case (int)TaskResultStatus.Cancel:
                case (int)TaskResultStatus.Complated:
                    {
                        var section = _sigerProjectLevelSection.Get(f => f.id == taskObj.sectionid);
                        if (section != null)
                        {
                            AutoProcess(section.parentid);
                        }
                        break;
                    }
                case (int)TaskResultStatus.Waiting:
                case (int)TaskResultStatus.Produce:
                default:
                    {
                        break;
                    }
            }
            return new ObjectResult(CommonEnum.Succefull);
        }

        /// <summary>
        /// 创建自动 Task任务
        /// </summary>
        /// <param name="line"></param>
        void AutoProcess(int line)
        {
            var lineMode = _automationLineMode.Get(f => f.projectId == PID && f.section == line);
            if (lineMode==null)
            {
                Logger.WriteLineInfo($"AutoProcess 产线模式未找到");
                throw new BadRequestException(AccEnum.LineModeNotfound);
            }
            if (lineMode.mode==0)
            {
                Logger.WriteLineInfo($"AutoProcess 手动模式");
                //手动模式时 退出
                return;
            }

            /*
            //自动Task任务 顺序 
            //1.清洗机下料
            //2.其他设备上料
            //3.其他设备下料 
            */
            var stationDicts = _sigerDict.GetDataByCat(AccDictCost.Automation, PID);
            if (!stationDicts.Any())
            {
                Logger.WriteLineInfo($"AutoProcess 未配置设备类型字典");
                return;
            }

            var updownDic= stationDicts.Where(s => s.dkey == DictKeyValConst.UploadloadStation);
            var uploadStations = updownDic.Select(f => f.dval).ToList();

            /* 自动任务创建只有CNC 设备;排除上料设备（手动任务） */


            var dictClean = stationDicts.FirstOrDefault(s=>s.dkey==DictKeyValConst.CleanStation);
            if (dictClean==null)
            {
                Logger.WriteLineInfo($"AutoProcess 未配置清洗机字典");
                return;
            }

            // 获取可用 设备状态列表
            var machineStatusList = _automationMachineStatus.GetList(f => f.projectId == PID && f.enable == 1);
            if (!machineStatusList.Any())
            {
                Logger.WriteLineInfo($"AutoProcess 无可用状态的设备");
                return;
            }
            //优先级1 ：清洗机完成 。待下料
            var cleanMachine = machineStatusList.FirstOrDefault(f => f.machineid == dictClean.dval.ToInt());
            if (cleanMachine!=null)
            {
                if (cleanMachine.status == (int)Automation.MachineStatus.Complated)
                {
                    Logger.WriteLineInfo($"AutoProcess 有清洗机完成，创建清洗剂Task");
                    CreateTask(cleanMachine,TaskActionType.Unload, TaskAction.Step_QXJ_LK, uploadStations);
                    return; //完成当前任务 退出
                }
            }


            //优先级2 ：其他设备待上料 (立库->加工中心)
            var freeMachine = machineStatusList.FirstOrDefault(f=>f.status==(int)Automation.MachineStatus.Waiting);
            if (freeMachine != null)
            {
                Logger.WriteLineInfo($"AutoProcess 普通空闲，创建普通设备上料Task");
                CreateTask(freeMachine,TaskActionType.Load ,TaskAction.Step_LK_JGZX, uploadStations);
                return; //完成当前任务 退出
            }
            //优先级3：其他设备下料  (加工中心 ->立库)
            if (cleanMachine != null)
            {
                var fullMachine = machineStatusList.FirstOrDefault(f => f.status == (int)Automation.MachineStatus.Complated);
                if (fullMachine != null && cleanMachine.status==(int)Automation.MachineStatus.Waiting)
                {
                    Logger.WriteLineInfo($"AutoProcess 普通空闲，创建普通设备下料Task ");
                    CreateTask(fullMachine,TaskActionType.Unload, TaskAction.Step_JGZX_QXJ, uploadStations);

                    return; //完成当前任务 退出
                }
            }
        }


        /// <summary>
        /// 创建自动任务
        /// </summary>
        /// <param name="machineStatus"></param>
        /// <param name="actionType"></param>
        /// <param name="taskAction"></param>
        /// <param name="uploadStations"></param>
        void CreateTask(siger_automation_machine_status machineStatus,TaskActionType actionType, TaskAction taskAction,List<string>uploadStations)
        {
            var uploadPostion= uploadStations.Exists(f => f.Contains(machineStatus.section.ToString()));
            if (uploadPostion)
            {
                Logger.WriteLineInfo($"CreateTask 上料料工站 无需自动创建任务 ");
                return;
            }
            //j检查工装监控状态
            var monitor = _automationFixtureMonitor.Get(f => f.section == machineStatus.section);
            if (monitor==null)
            {
                Logger.WriteLineInfo($"CreateTask 工装监控状态无数据，请确认业务链正确 ");
                return;
            }
            if (monitor.section==0)
            {
                Logger.WriteLineInfo($"CreateTask 工装监控状态无当前工站信息，请确认业务链正确 ");
                return;
            }


            _automationTaskList.Insert(new siger_automation_task_list
            {
                projectId = PID,
                sectionid = machineStatus.section,
                trigger = TaskTrigerType.Auto,
                action = taskAction,
                actiontype = ExcueType.None,
                tasktype = actionType,
                triggertime = DateTime.Now,
                completetime = DateTime.MinValue,
                operatetime = DateTime.MinValue,
                send = 0,
                operater = 0,
                status = 1,
                 fixtureguid=monitor.fixtureguid,
                productcode=monitor.productCode,
                locationid=monitor.locationId,
                ordercode=monitor.ordernumber,
                sn=monitor.sn, 
                remark="自动任务"
                
            });
            

            if (_unitOfWork.Commit() > 0)
                Logger.WriteLineInfo($"CreateTask 工站 完成");
            else
                Logger.WriteLineInfo($"CreateTask 工站 失败");
        }



    }
}
