using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using Siger.Middlelayer.AccRepository.Entities;
using Siger.Middlelayer.AccRepository.Repositories.Interface;
using Siger.Middlelayer.AccRepository.Request;
using Siger.Middlelayer.AccRepository.Response;
using Siger.Middlelayer.Common;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Share.Constant;
using Siger.Middlelayer.Share.Enum.ModuleEnum;
using Siger.Middlelayer.Common.Configuration;
using Siger.Middlelayer.Common.Helpers;
using Newtonsoft.Json;
using NPOI.SS.Formula;

namespace Siger.ApiACC.Controllers
{

    public class AutomationOperateController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly ISigerDict _sigerDict;
        private readonly IAutomationMachineStatus _automationMachineStatus;
        private readonly ISigerProjectMachineAttributionRepository _sigerProjectMachineAttribution;
        private readonly IAutomationTaskListRepository _automationTaskList;
        private readonly IProductPlanDetails _planDetails;
        private readonly IProductPlanRepository _productPlan;
        private readonly IAutomationFixtureMonitor _automationFixtureMonitor;
        private readonly IAutomationFixtureToolsProductRepository _automationFixtureToolsProduct;
        private readonly IAutomationFixtureToolsRepository _automationFixtureTools;
        private readonly IAutomationLocationRepository _automationLocation;
        private readonly IAutomationLineMode _automationLine;

        public AutomationOperateController(IUnitOfWork unitOfWork,ISigerProjectLevelSectionRepository sigerProjectLevelSection , ISigerDict sigerDict,IAutomationMachineStatus  automationMachineStatus,ISigerProjectMachineAttributionRepository sigerProjectMachineAttribution,IAutomationTaskListRepository automationTaskList,
            IProductPlanDetails planDetails,IProductPlanRepository productPlan,IAutomationFixtureMonitor automationFixtureMonitor ,IAutomationFixtureToolsProductRepository automationFixtureToolsProduct,IAutomationFixtureToolsRepository automationFixtureTools, IAutomationLocationRepository automationLocation, IAutomationLineMode automationLine)
        {
            _unitOfWork = unitOfWork;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _sigerDict = sigerDict;
            _automationMachineStatus = automationMachineStatus;
            _sigerProjectMachineAttribution = sigerProjectMachineAttribution;
            _automationTaskList = automationTaskList;
            _planDetails = planDetails;
            _productPlan = productPlan;
            _automationFixtureMonitor = automationFixtureMonitor;
            _automationFixtureToolsProduct = automationFixtureToolsProduct;
            _automationFixtureTools = automationFixtureTools;
            _automationLocation = automationLocation;
            _automationLine = automationLine;
        }

        /// <summary>
        /// 获取字典配置 
        /// </summary>
        /// <param name="line">产线</param>
        /// <param name="type">类型：0：上料  1：检验</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetloadStation(int line,int type)
        {
            var stationDicts = _sigerDict.GetDataByCat(AccDictCost.Automation, ProjectId);
            if (!stationDicts.Any())
            {
                Logger.WriteLineInfo($"GetloadStation 未配置设备类型字典");
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var loadStation=new List<string>();

            if (type==0)
            {
                var dictLoad = stationDicts.Where(s => s.dkey == DictKeyValConst.UploadloadStation);
                if (!dictLoad.Any())
                {
                    Logger.WriteLineInfo($"GetloadStation 未配置上下料工站字典");
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                loadStation = dictLoad.Select(s => s.dval).ToList();
            }else
            {
                var dictLoad = stationDicts.Where(s => s.dkey == DictKeyValConst.CleanStation);
                if (!dictLoad.Any())
                {
                    Logger.WriteLineInfo($"GetloadStation 未配置清洗工站字典");
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                loadStation = dictLoad.Select(s => s.dval).ToList();
            }
           

            var data = new List<ResponseLoadStation>();

            foreach (var station in loadStation)
            {
                var section = _sigerProjectLevelSection.Get(f => f.id == station.ToInt() && f.parentid==line && f.status == (int)RowState.Valid);
                if (section == null)
                    continue;
                var machintAttr = _sigerProjectMachineAttribution.Get(f => f.station == section.id);
                if(machintAttr==null)
                {
                    Logger.WriteLineInfo($"GetloadStation 未配置工站字典");
                    continue;
                }
                var loadStatus = (int)Automation.MachineStatus.Waiting;
                var machineStatus = _automationMachineStatus.Get(f => f.section == section.id);
                if (machineStatus==null)
                {
                    _automationMachineStatus.Insert(new siger_automation_machine_status
                    {
                         projectId=ProjectId,
                         enable=1,
                         machineid=machintAttr.machine,
                         section=section.id,
                         updatetime=DateTime.Now
                    });

                }else
                {

                    loadStatus = machineStatus.status;
                }
                data.Add(new ResponseLoadStation { 
                 section=section.id,
                 title=section.title,
                 status=loadStatus
                });
            }
            _unitOfWork.Commit();
           
            return new ObjectResult(data);
        }


        /// <summary>
        /// 查询状态
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetLoadingState(int section)
        {

           
            var monitor = _automationFixtureMonitor.Get(f => f.section == section);
            var result = new ResponsePlanlFixtureInfo
            {
                OrderNumber = monitor!=null? monitor.ordernumber:"",
                FixtureGuid = monitor != null ? monitor.fixtureguid:"",
                FixtureName = monitor != null ? monitor.fixturename:"",
                ProductCode = monitor != null ? monitor.productCode:"",
                ProductName = monitor != null ? monitor.productName:"",
                Sn = monitor != null ? monitor.sn:"",
                status = monitor != null ? monitor.status:(int)Automation.MachineStatus.Waiting,
                Location = monitor != null ? monitor.locationId:0,
            };
            return new ObjectResult(result);
        }
        /// <summary>
        /// 手动下发
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IActionResult Send(int id)
        {
            var taskobj = _automationTaskList.Get(f => f.id == id);
            if (taskobj==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (taskobj.send==1)
            {
                throw new BadRequestException(AccEnum.TaskIsSend);
            }
            var levelsection = _sigerProjectLevelSection.Get(taskobj.sectionid);
            var line = levelsection != null ? levelsection.parentid : 0;
            var lineMode = _automationLine.Get(f => f.section == line );
            if (lineMode==null)
            {
                throw new BadRequestException(AccEnum.LineModeNotfound);
            }
            if (lineMode.mode==1)
            {
                throw new BadRequestException(AccEnum.LineIsAutoMode);
            }
            var attr = _sigerProjectMachineAttribution.Get(f => f.station == taskobj.sectionid && f.status == 1);
            if (attr==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var host = GetHost();
            if (string.IsNullOrEmpty(host))
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            var sendToPLC = new RequestPLC
            {
                LineID=levelsection.parentid,
                RStation = attr.machine,
                Fixture = taskobj.fixtureguid,
                RequestForm = taskobj.no,
                RobotStep = (int)taskobj.action,
                StorageNo = taskobj.locationid,
                SN = taskobj.sn,
                Program = taskobj.programnumber
            };

            var result = PushTask(host, sendToPLC, out string message);
            if (!result)
            {
                Logger.WriteLineError($"TASK 下发失败 : {message}");
                throw new BadRequestException(CommonEnum.Fail);
            }
            taskobj.send = 1;
            _automationTaskList.Update(taskobj);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }
        private bool PushTask(string ip, RequestPLC request, out string msg)
        {
            msg = string.Empty;
            try
            {
                var param = JsonHelper.SerializerToJsonString(request);
                var retstring = HttpHelper.HttpPost($"{ip}{CommonConst.SenTaskToMES}", "application/json", param);
                var result = JsonConvert.DeserializeObject<ResponsePlC>(retstring);
                if (result.return_code != 0)
                {
                    msg = $"PushTask failed,URL{ip} input:{param } result :{result.return_desc}";
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                msg = ex.ToString();
            }
            return false;
        }
        private string GetHost()
        {
            var host = ConfigManager.GetValue("ProjectSetting", "Host", string.Empty);
            if (string.IsNullOrEmpty(host))
            {
                Logger.WriteLineError("DbSetting about [ProjectSetting] Host not found.");
                return null;
            }
            return host;
        }
        /// <summary>
        /// 扫描 
        /// </summary>
        /// <param name="code"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult ScanCode(string code,int id)
        {
            if (!string.IsNullOrEmpty(code))
            {
                var result = _automationFixtureToolsProduct.GetPlanFixtureInfo(ProjectId, code);
                if (result == null)
                {
                    throw new BadRequestException(AccEnum.FixtureOrderNulll);
                }
                var sn = _automationTaskList.CreateRandonSn(result.ProductCode);
                result.Sn = sn;
                return new ObjectResult(result);
            }
            if (id==0)
            {
                throw new BadRequestException(RequestEnum.ParameterMiss);
            }
            //下料 
            var unload = _automationFixtureToolsProduct.GetPlanFixtureInfoByLocation(ProjectId, id);
            if (unload == null)
            {
                throw new BadRequestException(AccEnum.FixtureOrderNulll);
            }
            return new ObjectResult(unload);

        }
        /// <summary>
        /// 准备上料 -生成指令 load （立库->上料位）
        /// </summary>
        /// <param name="loading"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Loading([FromBody]requestAutomationLoading loading)
        {

            var machineAttr = _sigerProjectMachineAttribution.Get(f => f.station == loading.section && f.status == (int)RowState.Valid);
            if (machineAttr==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var machineStatus = _automationMachineStatus.Get(f => f.machineid == machineAttr.machine);
            if (machineStatus == null)
            {
                // throw new BadRequestException(CommonEnum.RecordNotFound);
                //上料设备状态与PLC 无关，
                //需要手动插入
                _automationMachineStatus.Insert(new siger_automation_machine_status
                {
                    enable = 1,
                    section = loading.section,
                    machineid = machineAttr.machine,
                    projectId = ProjectId,
                    status = (int)Automation.MachineStatus.Waiting,
                    updatetime = DateTime.Now
                });
            }
            else
            {
                if (machineStatus.enable == 0)
                {
                    throw new BadRequestException(AccEnum.MachineDisable);
                }
                if (machineStatus.status != (int)Automation.MachineStatus.Waiting)
                {
                    throw new BadRequestException(AccEnum.MachineBusy);
                }
            }
            if (!_automationTaskList.CanTask(ProjectId,loading.section))
            {
                throw new BadRequestException(AccEnum.TaskProcessing);
            }

            var plandts = _planDetails.Get(f => f.projectId == ProjectId && f.OrderNumber == loading.code);
            if (plandts==null)
            {
                throw new BadRequestException(CncEnum.PlanHasExist);
            }
            var plan = _productPlan.Get(f => f.id == plandts.PlanId);
            if (plan == null)
            {
                throw new BadRequestException(CncEnum.PlanHasExist);
            }
            //检查工装
            var fixtureToolsObj = _automationFixtureTools.GetProductFixtureLocation(ProjectId,loading.guid);
            //var fixtureToolsObj = _automationFixtureToolsProduct.GetFixtureInfoByProductCode(ProjectId, plan.product_code);
            if (fixtureToolsObj == null)
            {
                throw new BadRequestException(AccEnum.FixtureToolsIsNone);
            }
            var taskNo = _automationTaskList.CrateTaskNumber(Automation.TaskTrigerType.Manual);
            var sn = _automationTaskList.CreateRandonSn(plan.product_code);

            _automationTaskList.Insert(new siger_automation_task_list
            {
                 no=taskNo,
                 action= Automation.TaskAction.Step_LK_SXLW,
                 actiontype= Automation.ExcueType.None,
                 triggertime=DateTime.Now,
                 tasktype= Automation.TaskActionType.Load,
                 operater=UserId,
                 operatetime=DateTime.MinValue,
                 sectionid=loading.section,
                 send=0,
                 status=1,
                 completetime=DateTime.MinValue,
                 trigger= Automation.TaskTrigerType.Manual,
                 projectId=ProjectId,
                 productid=plan.product_id,
                 sn=sn,
                 ordercode=plandts.OrderNumber,
                 fixtureguid= fixtureToolsObj.FixtureGuid,
                 fixturename=fixtureToolsObj.FixtureCode,
                 locationid=fixtureToolsObj.Location,
                 productcode=plan.product_code,
                 processid=0,
                 programnumber="",
                 remark ="手动任务-准备上料",
                 
            });


            var monitor = _automationFixtureMonitor.Get(f => f.fixtureguid == fixtureToolsObj.FixtureGuid);
            if (monitor==null)
            {
                _automationFixtureMonitor.Insert(new siger_automation_fixture_tools_monitor
                {
                     fixtureguid=fixtureToolsObj.FixtureGuid,
                     fixturename=fixtureToolsObj.FixtureName,
                     projectId=ProjectId,
                     section=loading.section,
                     sn=sn,
                     createtime=DateTime.Now,
                     updatetime=DateTime.Now,
                     status=(int)Automation.MachineStatus.Produce,
                     productId=plan.product_id,
                     productCode=plan.product_code,
                     productName=plan.product_name,
                     ordernumber=plandts.OrderNumber,
                     locationId= fixtureToolsObj.Location
                });
            }
            else
            {
                monitor.sn = sn;
                monitor.section = loading.section;
                monitor.updatetime = DateTime.Now;
                monitor.status = (int)Automation.MachineStatus.Produce;
                monitor.productId = plan.product_id;
                monitor.productName = plan.product_name;
                monitor.productCode = plan.product_code;
                monitor.ordernumber = plandts.OrderNumber;
                monitor.locationId = fixtureToolsObj.Location;
               
                _automationFixtureMonitor.Update(monitor);
            }


            if (_unitOfWork.Commit() > 0)
            {
                Logger.WriteLineError($"手动任务创建成功-{Siger.Middlelayer.Common.Helpers.EnumHelper.GetEnumDesc(Automation.TaskAction.Step_LK_SXLW)}");
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 安装完成 -生成指令 unload
        /// </summary>
        /// <param name="assemble"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult CompalateAssemble([FromBody]requestAutoCompalateAssemble assemble)
        {
            var machineStatus = _automationMachineStatus.Get(f => f.section == assemble.section);
            if (machineStatus==null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (machineStatus.enable == 0)
            {
                throw new BadRequestException(AccEnum.MachineDisable);
            }
            //if (machineStatus.status == (int)Automation.MachineStatus.Waiting)
            //{
            //    throw new BadRequestException(AccEnum.MachineOnFree);
            //}
            //if (machineStatus.status == (int)Automation.MachineStatus.Complated)
            //{
            //    throw new BadRequestException(AccEnum.MachineProCompalate);
            //}

            if (!_automationTaskList.CanTask(ProjectId, assemble.section))
            {
                throw new BadRequestException(AccEnum.TaskProcessing);
            }
            //创建 安装完成动作
            var monitor = _automationFixtureMonitor.Get(f => f.projectId == ProjectId && f.section == assemble.section);
            if (monitor==null)
            {
                throw new BadRequestException(AccEnum.MonitorNotfound);
            }
            //移出 上料位
        
            var taskNo = _automationTaskList.CrateTaskNumber(Automation.TaskTrigerType.Manual);
            _automationTaskList.Insert(new siger_automation_task_list
            {
                no = taskNo,
                action = Automation.TaskAction.Step_SXLW_LK,
                actiontype = Automation.ExcueType.None,
                triggertime = DateTime.Now,
                tasktype = Automation.TaskActionType.Load,
                operater = UserId,
                operatetime = DateTime.Now,
                sectionid = assemble.section,
                send = 0,
                status = 1,
                completetime = DateTime.MinValue,
                trigger = Automation.TaskTrigerType.Manual,
                projectId = ProjectId,
                productid = monitor.productId,
                sn = monitor.sn,
                ordercode = monitor.ordernumber,
                fixtureguid = monitor.fixtureguid,
                locationid = monitor.locationId,
                productcode = monitor.productCode,
                processid = 0,
                programnumber = "",
                remark = "手动任务-安装完成",

            });

            if (_unitOfWork.Commit() > 0)
            {
                Logger.WriteLineError($"手动任务创建成功-{Siger.Middlelayer.Common.Helpers.EnumHelper.GetEnumDesc(Automation.TaskAction.Step_SXLW_LK)}");
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 准备下料
        /// </summary>
        /// <param name="unloading"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Unloading([FromBody]requestAutomationUnloading unloading)
        {
            //var monitor = _automationFixtureMonitor.Get(f => f.section == unloading.section);
            //if (monitor == null)
            //{
            //    Logger.WriteLineInfo($"AutoProcess 找不到CNC监控信息");
            //    return new ObjectResult(CommonEnum.RecordNotFound);
            //}
            //if (string.IsNullOrEmpty( monitor.sn))
            //{
            //    Logger.WriteLineInfo($"AutoProcess 找不到CNC监控SN信息");
            //    return new ObjectResult(CommonEnum.RecordNotFound);
            //}

            var location = _automationLocation.Get(f => f.locationid == unloading.locationid);
            if (location==null)
            {
                return new ObjectResult(CommonEnum.RecordNotFound);
            }
            if (string.IsNullOrEmpty( location.sn))
            {
                return new ObjectResult(AccEnum.LocationNoSn);
            }
            var levelSection = _sigerProjectLevelSection.Get(f => f.id == unloading.section);
            var lineMode = _automationLine.Get(f => f.section ==levelSection.parentid);

            if (lineMode==null)
            {
                return new ObjectResult(AccEnum.LineModeNotfound);
            }
            
            //TODO
            //1. 有检验状态  （立库-》检验工位）
            //2. 无检验状态  （立库-》上下料工位）
            var taskNo = _automationTaskList.CrateTaskNumber(Automation.TaskTrigerType.Manual);
   
            _automationTaskList.Insert(new siger_automation_task_list
            {
                no = taskNo,
                action = lineMode.inspect==1?Automation.TaskAction.Step_LK_CJT: Automation.TaskAction.Step_LK_SXLW,
                actiontype = Automation.ExcueType.None,
                triggertime = DateTime.Now,
                tasktype = Automation.TaskActionType.Load,
                operater = UserId,
                operatetime = DateTime.MinValue,
                sectionid = unloading.section,
                send = 0,
                status = 1,
                completetime = DateTime.MinValue,
                trigger = Automation.TaskTrigerType.Manual,
                projectId = ProjectId,
                productid = location.productid,
                sn = location.sn,
                ordercode = location.ordernumber,
                fixtureguid = location.fixturetools,
                locationid = location.locationid,
                productcode = location.productcode,
                processid = 0,
                programnumber = "",
                remark = "手动任务-准备上料",

            });
            var monitor = _automationFixtureMonitor.Get(f => f.section == unloading.section);
            if (monitor == null)
            {
                _automationFixtureMonitor.Insert(new siger_automation_fixture_tools_monitor
                {
                    fixtureguid = location.fixturetools,
                    fixturename = location.fixturename,
                    projectId = ProjectId,
                    section = unloading.section,
                    sn = location.sn,
                    createtime = DateTime.Now,
                    updatetime = DateTime.Now,
                    status = (int)Automation.MachineStatus.Produce,
                    productId = location.productid,
                    productCode = location.productcode,
                    productName = location.productname,
                    ordernumber = location.ordernumber,
                    locationId = location.locationid
                });
            }
            else
            {
                monitor.sn = location.sn;
       
                monitor.updatetime = DateTime.Now;
                monitor.status = (int)Automation.MachineStatus.Produce;
                monitor.productId = location.productid;
                monitor.productName = location.productname;
                monitor.productCode = location.productcode;
                monitor.ordernumber = location.ordernumber;
                monitor.locationId = location.locationid;

                _automationFixtureMonitor.Update(monitor);
            }

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 拆卸完成
        /// </summary>
        /// <param name="disassemble"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Disassemble([FromBody]Requestdisassemble disassemble)
        {

            var machineStatus = _automationMachineStatus.Get(f => f.section == disassemble.section);
            if (machineStatus == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (machineStatus.enable == 0)
            {
                throw new BadRequestException(AccEnum.MachineDisable);
            }

            if (!_automationTaskList.CanTask(ProjectId, disassemble.section))
            {
                throw new BadRequestException(AccEnum.TaskProcessing);
            }
            //创建 安装完成动作
            var monitor = _automationFixtureMonitor.Get(f => f.projectId == ProjectId && f.section == disassemble.section);
            if (monitor == null)
            {
                throw new BadRequestException(AccEnum.MonitorNotfound);
            }
            //移出 上料位
            monitor.section = 0;
            var taskNo = _automationTaskList.CrateTaskNumber(Automation.TaskTrigerType.Manual);
            _automationTaskList.Insert(new siger_automation_task_list
            {
                no = taskNo,
                action = Automation.TaskAction.Step_SXLW_LK,
                actiontype = Automation.ExcueType.None,
                triggertime = DateTime.Now,
                tasktype = Automation.TaskActionType.Load,
                operater = UserId,
                operatetime = DateTime.Now,
                sectionid = disassemble.section,
                send = 0,
                status = 1,
                completetime = DateTime.MinValue,
                trigger = Automation.TaskTrigerType.Manual,
                projectId = ProjectId,
                productid = monitor.productId,
                sn = monitor.sn,
                ordercode = monitor.ordernumber,
                fixtureguid = monitor.fixtureguid,
                locationid = monitor.locationId,
                productcode = monitor.productCode,
                processid = 0,
                programnumber = "",
                remark = "手动任务-拆卸完成",
            });

            if (_unitOfWork.Commit() > 0)
            {
                Logger.WriteLineError($"手动任务-拆卸完成-{Siger.Middlelayer.Common.Helpers.EnumHelper.GetEnumDesc(Automation.TaskAction.Step_SXLW_LK)}");
                return new ObjectResult(CommonEnum.Succefull);
            }
            else
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

   
    }
}
