package task

import (
	dal "LAPP_ACURA_MOM_BACKEND/dao/base"
	dal_pm "LAPP_ACURA_MOM_BACKEND/dao/pm"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	meta "LAPP_ACURA_MOM_BACKEND/meta/pm"
	model "LAPP_ACURA_MOM_BACKEND/models/pm"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"LAPP_ACURA_MOM_BACKEND/web/middleware/glog"
	"context"
	"log"
	"strconv"
	"time"
)

func CreateTask() {
	tick := time.Tick(60 * time.Second)
	for {
		select {
		case <-tick:
			CreateOrder()
		}
	}
}

//结构体
type TaskData struct {
	TaskType   string
	PmAsset    model.Asset
	PmTemplate model.Template
	PmService  model.Service
}

var taskChan = make(chan TaskData, 1000) //定义一个调度任务通道

/****
*生成维护工单
***************/
func CreateOrder() {

	//创建继承Baxkground的子节点Context
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	go doSth(ctx)

	data := make([]model.CreateData, 0)
	//第一步，多表联查出所有的数据
	engine := db.Eloquent.Master()
	query := engine.Table("PM_ASSET")
	query = query.Join("INNER", "PM_AssetTemplateLst", "PM_Asset.PlantNr = PM_AssetTemplateLst.PlantNr and PM_Asset.AssetNr = PM_AssetTemplateLst.AssetNr")
	query = query.Join("INNER", "PM_Template", "PM_Template.PlantNr = PM_AssetTemplateLst.PlantNr and PM_Template.MainTemplateNr = PM_AssetTemplateLst.MainTemplateNr")
	query = query.Join("INNER", "PM_TemplateServiceLst", "PM_Template.PlantNr = PM_TemplateServiceLst.PlantNr and PM_Template.MainTemplateNr = PM_TemplateServiceLst.MainTemplateNr")
	query = query.Join("INNER", "PM_Service", "PM_Service.PlantNr = PM_TemplateServiceLst.PlantNr and PM_Service.MainServiceNr = PM_TemplateServiceLst.MainServiceNr")

	query = query.Where("PM_Service.SchedType = ?", "AUTO")
	err := query.Find(&data)
	if err != nil {
		return
	}
	//第二步，把所有的服务调度放到channel
	for _, v := range data {
		//判断激活状态
		if utils.ValueIsEmpty(v.Service.EnabledToggle) {
			continue
		}
		dataone := TaskData{}
		dataone.PmService = v.Service
		dataone.PmTemplate = v.Template
		dataone.PmAsset = v.Asset
		//判断taskType
		if v.Service.MaintByDateToggle {
			dataone.TaskType = "A" //A是按照日期维护
		} else if v.Service.MaintByHourToggle {
			dataone.TaskType = "B" //B是按照小时维护
		} else if v.Service.MaintByMileageToggle {
			dataone.TaskType = "C" //C是按照仪表值维护
		} else if v.Service.NeedScheduleToggle {
			dataone.TaskType = "D" //D是按照调度维护
		} else {
			continue
		}
		taskChan <- dataone
	}
}

//生成任务工单
func doSth(ctx context.Context) {
	engine := db.Eloquent.Master()
	//第三步，启动协程，从channel里读取数据，根据服务维护日期进入不同的方法里
	for {
		select {
		case <-ctx.Done():
			return
		case task, ok := <-taskChan:
			if !ok {
				log.Println("调度生成终止")
				return //停机退出
			}
			session := engine.NewSession()
			defer session.Close()

			dao_workorder := dal_pm.NewWorkOrderDAO(session, task.PmService.PlantNr, "PM_Service")
			snrDao := dal.NewSnrDAO(session, task.PmService.PlantNr, "PM_Service")
			dao_serviceattrlst := dal_pm.NewServiceAttrLstDAO(session, task.PmService.PlantNr, "PM_Service")
			dao_workorderattrlst := dal_pm.NewWorkOrderAttrLstDAO(session, task.PmService.PlantNr, "PM_Service")
			dao_workcalendarlst := dal.NewWorkCalendarLstDAO(session, task.PmAsset.PlantNr, "PM_Service")
			dao_AssetKpi := dal_pm.NewAssetKpiDAO(session, task.PmAsset.PlantNr, "PM_Service")

			switch task.TaskType {
			case "A":
				//当前零点时间
				today := utils.GetZeroTime(time.Now())
				//逻辑：判断是否到了维护时间，（当前时间戳-起始时间戳）%间隔时间
				t1 := utils.TimeFormat(time.Now(), "yyyyMMdd")
				t2 := task.PmService.DueDateOn
				time1, _ := utils.TimeParseyyyyMMdd(t1)
				time2, _ := utils.TimeParseyyyyMMdd(t2.ToString())
				timelen := int(time1.Unix()) - int(time2.Unix())
				timeunit := task.PmService.DueDateInterval
				glog.InfoExtln("维护工单A", "Mainservicenr:", task.PmService.MainServiceNr)
				glog.InfoExtln("维护工单A", "t1:", t1)
				glog.InfoExtln("维护工单A", "t2:", task.PmService.DueDateOn)
				glog.InfoExtln("维护工单A", "timelen:", timelen)
				glog.InfoExtln("维护工单A", "timeunit:", timeunit)
				glog.InfoExtln("维护工单A", "res:", ((timelen / 86400) % timeunit))
				if res := ((timelen / 86400) % timeunit); res == 0 {
					//判断是否已经生成了维护工单，如果生成了，跳过
					tem, err := dao_workorder.SelectLastOne(task.PmService.PlantNr,task.PmService.MainServiceNr,task.PmAsset.AssetNr)
					if err!=nil {
						glog.InfoExtln("维护工单A", "err:", err)
						continue
					}
					//判断是否添加了服务
					t2now, _ := utils.TimeParse(tem.ActBegTime.ToString())
					endtime := t2now.AddDate(0, 0, timeunit)
					//先把时间字符串格式化成相同的时间类型
					nowtime, _ := utils.TimeParseyyyyMMdd(t1)

					if nowtime.Before(endtime) {
						//处理逻辑
						glog.InfoExtln("维护工单A", "nowtime:", nowtime)
						glog.InfoExtln("维护工单A", "endtime:", endtime)
						continue
					}

					glog.InfoExtln("维护工单A", "endtime:", endtime)

					workOrderId, err := snrDao.GetNextSnr("WorkOrder")
					if err != nil {
						_ = session.Rollback()
						continue
					}
					//符合逻辑生成维护工单
					pm := new(model.WorkOrder)
					pm.PlantNr = task.PmService.PlantNr
					pm.MaintWorkOrderId = workOrderId
					pm.MainServiceNr = strconv.Itoa(task.PmService.MainServiceNr)
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.AssetNr = task.PmAsset.AssetNr
					pm.PlBegDat = grmi.Date(time.Now())
					pm.SchedBegTime = grmi.DateTime(time.Now())
					endtime = today.AddDate(0, 0, timeunit)
					pm.SchedEndTime = grmi.DateTime(endtime)
					pm.ActBegTime = grmi.DateTime(today)
					pm.ActEndTime = grmi.DateTime(endtime)
					//查询当天是否是工作日,如果是跳过
					engine := db.Eloquent.Master()
					session := engine.NewSession()
					defer session.Close()
					dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.PlantNr, "PM_Service")
					ok := dao.IsWorkDate(t1)
					if !ok {
						result, err := dao.SelectNearWorkDate(t1)
						if err != nil {
							_ = session.Rollback()
							continue
						}
						if result == nil {
							_ = session.Rollback()
							continue
						} else {
							Acttime := result.WorkDate.Restore()
							pm.ActBegTime = grmi.DateTime(Acttime)
							Actendtime := Acttime.AddDate(0, 0, timeunit)
							glog.InfoExtln("维护工单A", "Actendtime:", Actendtime)
							pm.ActEndTime = grmi.DateTime(Actendtime)
						}
					}

					pm.MaintType = task.PmService.MaintType
					err = dao_workorder.InsertOne(pm)
					if err != nil {
						_ = session.Rollback()
						continue
					}

					data, err := dao_serviceattrlst.Select([]grmi.Predicate{meta.ServiceAttrLst_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.ServiceAttrLst_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
					if err != nil {
						_ = session.Rollback()
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(model.WorkOrderAttrLst)
						at.PlantNr = v.PlantNr
						at.Descr = v.Descr
						at.MainServiceNr = v.MainServiceNr
						at.MaintWorkOrderId = workOrderId
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.ParaValue = v.ParaValue
						at.AttrNr = v.AttrNr
						err := dao_workorderattrlst.InsertOne(at)
						if err != nil {
							_ = session.Rollback()
							continue
						}
					}
				}
				session.Commit()
			case "B":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()

				ok := dao_workcalendarlst.IsWorkDate(today)
				if !ok {
					continue
				}

				//逻辑：起始时间+间隔时间，
				t1 := utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
				//判断是否已经生成了维护工单，如果生成了，跳过
				tem, err := dao_workorder.SelectLastOne(task.PmService.PlantNr,task.PmService.MainServiceNr,task.PmAsset.AssetNr)
				if err != nil{
					glog.InfoExtln("维护工单B", "err:", err)
					continue
				}

				glog.InfoExtln("维护工单B", "tem:", tem)

				time2, _ := utils.TimeParse(tem.ActBegTime.ToString())
				time1, _ := utils.TimeParse(t1)
				timelen := int(time1.Unix()) - int(time2.Unix())
				timeunit := task.PmService.DueHourInterval

				glog.InfoExtln("维护工单B", "Mainservicenr:", task.PmService.MainServiceNr)
				glog.InfoExtln("维护工单B", "tem.Actbegtime:", tem.ActBegTime)
				glog.InfoExtln("维护工单B", "timelen:", timelen)
				glog.InfoExtln("维护工单B", "timeunit:", timeunit)
				if (timelen - timeunit*3600) > 0 {
					workOrderId, err := snrDao.GetNextSnr("WorkOrder")
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						continue
					}

					//查询当天是否是工作日,如果是跳过
					engine := db.Eloquent.Master()
					session := engine.NewSession()
					defer session.Close()

					res := dao_workcalendarlst.IsWorkDate(today)
					if !res {
						continue
					}

					//符合逻辑生成维护工单
					pm := new(model.WorkOrder)
					pm.PlantNr = task.PmService.PlantNr
					pm.MaintWorkOrderId = workOrderId
					pm.MainServiceNr = strconv.Itoa(task.PmService.MainServiceNr)
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.AssetNr = task.PmAsset.AssetNr
					pm.PlBegDat = grmi.Date(time.Now())
					timeNow := time.Now()
					pm.SchedBegTime = grmi.DateTime(timeNow)
					//计算结束时间
					endtime := timeNow.Add(time.Duration(timeunit) * time.Hour)
					glog.InfoExtln("维护工单B", "timeunit:", timeunit)
					pm.SchedEndTime = grmi.DateTime(endtime)
					pm.ActBegTime = grmi.DateTime(timeNow)
					pm.ActEndTime = grmi.DateTime(endtime)
					pm.MaintType = task.PmService.MaintType
					err = dao_workorder.InsertOne(pm)
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						_ = session.Rollback()
						continue
					}

					data, err := dao_serviceattrlst.Select([]grmi.Predicate{meta.ServiceAttrLst_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.ServiceAttrLst_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						_ = session.Rollback()
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(model.WorkOrderAttrLst)
						at.PlantNr = v.PlantNr
						at.Descr = v.Descr
						at.MainServiceNr = v.MainServiceNr
						at.MaintWorkOrderId = workOrderId
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.ParaValue = v.ParaValue
						at.AttrNr = v.AttrNr
						err := dao_workorderattrlst.InsertOne(at)
						if err != nil {
							glog.InfoExtln("维护工单B", "err:", err)
							_ = session.Rollback()
							continue
						}
					}
				}
				session.Commit()
			case "C":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()
				dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.PlantNr, "PM_Service")
				ok := dao.IsWorkDate(today)
				if !ok {
					continue
				}
				//逻辑：仪表值
				//第一步：查询资产阈值表，判断是否是触发状态
				info, err := dao_AssetKpi.Select([]grmi.Predicate{meta.AssetKpi_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.AssetKpi_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
				if err != nil {
					continue
				}
				for _, pmaInfo := range info {
					switch pmaInfo.KpiType {
					case 1:
						if pmaInfo.TriggerStatus == 1 {
							continue
						}
						if pmaInfo.ThresholdVal < pmaInfo.ActualVal {
							continue
						}

						//第二步：生成维护工单，
						//逻辑：根据调度时间维护
						workOrderId, err := snrDao.GetNextSnr("WorkOrder")
						if err != nil {
							continue
						}
						log.Printf("流水号id:%v", workOrderId)
						if err != nil {
							return
						}
						//符合逻辑生成维护工单
						pm := new(model.WorkOrder)
						pm.PlantNr = task.PmService.PlantNr
						pm.MaintWorkOrderId = workOrderId
						pm.MainServiceNr = strconv.Itoa(task.PmService.MainServiceNr)
						pm.Descr = task.PmService.Descr
						pm.Status = 26
						pm.Priority = task.PmService.Priority
						pm.AssetNr = task.PmAsset.AssetNr
						pm.PlBegDat = grmi.Date(time.Now())
						pm.SchedBegTime = grmi.DateTime(time.Now())
						timenow := utils.ValueToString(task.PmService.MainTimeLen, "")
						m, _ := time.ParseDuration(timenow + "h")
						pm.SchedEndTime = grmi.DateTime(time.Now().Add(m))
						pm.ActBegTime = pm.SchedBegTime
						pm.ActEndTime = pm.SchedEndTime
						pm.MaintType = task.PmService.MaintType
						err = dao_workorder.InsertOne(pm)
						if err != nil {
							_ = session.Rollback()
							continue
						}
						data, err := dao_serviceattrlst.Select([]grmi.Predicate{meta.ServiceAttrLst_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.ServiceAttrLst_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
						if err != nil {
							_ = session.Rollback()
							continue
						}
						//生成属性
						for _, v := range data {
							at := new(model.WorkOrderAttrLst)
							at.PlantNr = v.PlantNr
							at.Descr = v.Descr
							at.MainServiceNr = v.MainServiceNr
							at.MaintWorkOrderId = workOrderId
							at.Pos = v.Pos
							at.Parameter = v.Parameter
							at.ParaValue = v.ParaValue
							at.AttrNr = v.AttrNr
							err := dao_workorderattrlst.InsertOne(at)
							if err != nil {
								_ = session.Rollback()
								continue
							}
						}
						//第三步：锁定触发器状态
						pmaInfo.TriggerStatus = 1
						err = dao_AssetKpi.UpdateOne(&pmaInfo)
						if err != nil {
							_ = session.Rollback()
							continue
						}

					case 2:
						if pmaInfo.CounterVal < pmaInfo.CounterCycleVal {
							continue
						}
						//第二步：生成维护工单，
						//逻辑：根据调度时间维护
						workOrderId, err := snrDao.GetNextSnr("WorkOrder")
						if err != nil {
							continue
						}
						log.Printf("流水号id:%v", workOrderId)
						if err != nil {
							return
						}
						//符合逻辑生成维护工单
						pm := new(model.WorkOrder)
						pm.PlantNr = task.PmService.PlantNr
						pm.MaintWorkOrderId = workOrderId
						pm.MainServiceNr = strconv.Itoa(task.PmService.MainServiceNr)
						pm.Descr = task.PmService.Descr
						pm.Status = 26
						pm.Priority = task.PmService.Priority
						pm.AssetNr = task.PmAsset.AssetNr
						pm.PlBegDat = grmi.Date(time.Now())
						pm.SchedBegTime = grmi.DateTime(time.Now())
						timenow := utils.ValueToString(task.PmService.MainTimeLen, "")
						m, _ := time.ParseDuration(timenow + "h")
						pm.SchedEndTime = grmi.DateTime(time.Now().Add(m))
						pm.ActBegTime = pm.SchedBegTime
						pm.ActEndTime = pm.SchedEndTime
						pm.MaintType = task.PmService.MaintType

						dao_workorder.InsertOne(pm)
						if err != nil {
							_ = session.Rollback()
							continue
						}
						data, err := dao_serviceattrlst.Select([]grmi.Predicate{meta.ServiceAttrLst_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.ServiceAttrLst_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
						if err != nil {
							_ = session.Rollback()
							continue
						}
						//生成属性
						for _, v := range data {
							at := new(model.WorkOrderAttrLst)
							at.PlantNr = v.PlantNr
							at.Descr = v.Descr
							at.MainServiceNr = v.MainServiceNr
							at.MaintWorkOrderId = workOrderId
							at.Pos = v.Pos
							at.Parameter = v.Parameter
							at.ParaValue = v.ParaValue
							at.AttrNr = v.AttrNr
							err := dao_workorderattrlst.InsertOne(at)
							if err != nil {
								_ = session.Rollback()
								continue
							}
						}
						//第三步：计数清零
						pmaInfo.CounterCycleVal = 1
						err = dao_AssetKpi.UpdateOne(&pmaInfo)
						if err != nil {
							_ = session.Rollback()
							continue
						}
					}
				}
				session.Commit()
			case "D":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()

				ok := dao_workcalendarlst.IsWorkDate(today)
				if !ok {
					continue
				}
				//逻辑：起始时间+间隔时间，
				//判断是否已经生成了维护工单，如果生成了，跳过
				tem, err := dao_workorder.SelectLastOne(task.PmService.PlantNr,task.PmService.MainServiceNr,task.PmAsset.AssetNr)
				if err != nil {
					glog.InfoExtln("维护工单D", "err:", err)
					continue
				}
				time2, _ := utils.TimeParse(tem.ActBegTime.ToString())
				time1, _ := utils.TimeParseyyyyMMdd(today)
				timelen := int(time1.Unix()) - int(time2.Unix())
				if err != nil {
					continue
				}
				if timelen >= 0 {
					//逻辑：根据调度时间维护
					workOrderId, err := snrDao.GetNextSnr("WorkOrder")
					log.Printf("流水号id:%v", workOrderId)
					if err != nil {
						return
					}
					//符合逻辑生成维护工单
					pm := new(model.WorkOrder)
					pm.PlantNr = task.PmService.PlantNr
					pm.MaintWorkOrderId = workOrderId
					pm.MainServiceNr = strconv.Itoa(task.PmService.MainServiceNr)
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.AssetNr = task.PmAsset.AssetNr
					pm.PlBegDat = grmi.Date(time.Now())
					pm.SchedBegTime = grmi.DateTime(time.Now())
					timenow := utils.ValueToString(task.PmService.MainTimeLen, "")
					m, _ := time.ParseDuration(timenow + "h")
					pm.SchedEndTime = grmi.DateTime(time.Now().Add(m))
					pm.ActBegTime = pm.SchedBegTime
					pm.ActEndTime = pm.SchedEndTime
					pm.MaintType = task.PmService.MaintType
					err = dao_workorder.InsertOne(pm)
					if err != nil {
						continue
					}
					data, err := dao_serviceattrlst.Select([]grmi.Predicate{meta.ServiceAttrLst_PlantNr.NewPredicate(grmi.Equal, task.PmService.PlantNr), meta.ServiceAttrLst_MainServiceNr.NewPredicate(grmi.Equal, task.PmService.MainServiceNr)}, nil)
					if err != nil {
						_ = session.Rollback()
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(model.WorkOrderAttrLst)
						at.PlantNr = v.PlantNr
						at.Descr = v.Descr
						at.MainServiceNr = v.MainServiceNr
						at.MaintWorkOrderId = workOrderId
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.ParaValue = v.ParaValue
						at.AttrNr = v.AttrNr
						err := dao_workorderattrlst.InsertOne(at)
						if err != nil {
							continue
						}
					}
				}

			default:
				//进行非抢占式任务
			}
		}
	}
}
