package task

import (
	dal "LAPP_LF_MOM_BACKEND/dao/base"
	"LAPP_LF_MOM_BACKEND/db"
	"LAPP_LF_MOM_BACKEND/utils"
	"LAPP_LF_MOM_BACKEND/web/middleware/glog"
	"LAPP_LF_MOM_BACKEND/web/models"
	"log"
	"context"
	"time"
)

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

//结构体
type TaskData struct {
	TaskType   string
	PmAsset    models.PmAsset
	PmTemplate models.PmTemplate
	PmService  models.PmService
}

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

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

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

	data := make([]models.CreateData, 0)
	//第一步，多表联查出所有的数据
	engine := db.Eloquent.Master()
	query := engine.Table("pm_asset")
	query = query.Join("INNER", "pm_asset_templatelst", "pm_asset.finr = pm_asset_templatelst.finr and pm_asset.assetid = pm_asset_templatelst.assetid")
	query = query.Join("INNER", "pm_template", "pm_template.finr = pm_asset_templatelst.finr and pm_template.maintemplatenr = pm_asset_templatelst.maintemplatenr")
	query = query.Join("INNER", "pm_template_servicelst", "pm_template.finr = pm_template_servicelst.finr and pm_template.maintemplatenr = pm_template_servicelst.maintemplatenr")
	query = query.Join("INNER", "pm_service", "pm_service.finr = pm_template_servicelst.finr and pm_service.mainserviceid = pm_template_servicelst.mainservicenr")

	query = query.Where("pm_asset.finr = ? and pm_service.schedtype = ?", 100,"AUTO")
	err := query.Find(&data)
	if err != nil {
		return
	}
	//第二步，把所有的服务调度放到channel
	for _, v := range data {
		//判断激活状态
		if utils.ValueIsEmpty(v.PmService.Enabled) {
			continue
		}
		dataone := TaskData{}
		dataone.PmService = v.PmService
		dataone.PmTemplate = v.PmTemplate
		dataone.PmAsset = v.PmAsset
		//判断taskType
		if v.PmService.Maintbydate > 0 {
			dataone.TaskType = "A" //A是按照日期维护
		} else if v.PmService.Maintbyhour > 0 {
			dataone.TaskType = "B" //B是按照小时维护
		} else if v.PmService.Maintbymileage > 0 {
			dataone.TaskType = "C" //C是按照仪表值维护
		} else if v.PmService.Needschedule > 0 {
			dataone.TaskType = "D" //D是按照调度维护
		} else {
			continue
		}
		taskChan <- dataone
	}
}

//生成任务工单
func doSth(ctx context.Context) {
	//第三步，启动协程，从channel里读取数据，根据服务维护日期进入不同的方法里
	for {
		select {
		case <-ctx.Done():
			return
		case task, ok := <-taskChan:

			if !ok {
				log.Println("调度生成终止")
				return //停机退出
			}
			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)
				timelen := int(time1.Unix()) - int(time2.Unix())
				timeunit := task.PmService.Duedateinterval
				glog.InfoExtln("维护工单A", "Mainservicenr:", task.PmService.Mainserviceid)
				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 {

					//判断是否已经生成了维护工单，如果生成了，跳过
					pms := new(models.PmWo)
					pms.Finr = task.PmService.Finr
					pms.Mainservicenr = task.PmService.Mainserviceid
					pms.Assetid = task.PmAsset.Assetid
					tem, err := pms.SelectPmWoOne()
					if err != nil {
						glog.InfoExtln("维护工单A", "tem.Mainservicenr:", tem.Mainservicenr)
						continue
					}

					//判断是否添加了服务
					t2now, _ := utils.TimeParse(tem.Actbegtime)
					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)

					snr := new(models.Snrtab)
					snr.Finr = 100
					//生成ID
					woid, err := snr.GetNextSnr("WOID")
					if err != nil {
						continue
					}
					//符合逻辑生成维护工单
					pm := new(models.PmWo)
					pm.Finr = task.PmService.Finr
					pm.Maintwoid = woid
					pm.Mainservicenr = task.PmService.Mainserviceid
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.Assetid = task.PmAsset.Assetid
					pm.Plbegdat = utils.TimeFormat(time.Now(), "yyyyMMdd")
					pm.Schedbegtime = utils.TimeFormat(today, "yyyyMMddHHmmss")
					endtime = today.AddDate(0, 0, timeunit)
					pm.Schedendtime = utils.TimeFormat(endtime, "yyyyMMddHHmmss")
					pm.Actbegtime = utils.TimeFormat(today, "yyyyMMddHHmmss")
					pm.Actendtime = utils.TimeFormat(endtime, "yyyyMMddHHmmss")
					//查询当天是否是工作日,如果是跳过
					engine := db.Eloquent.Master()
					session := engine.NewSession()
					defer session.Close()
					dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.Finr, "pm_service")
					ok := dao.IsWorkDate(t1)
					if !ok{
						result,err :=dao.SelectNearWorkDate(t1)
						if err != nil {
							continue
						}
						if result == nil{
							continue
						}else{
							Acttime :=  result.WorkDate.Restore()
							pm.Actbegtime = utils.TimeFormat(Acttime, "yyyyMMddHHmmss")
							Actendtime := Acttime.AddDate(0,0,timeunit)
							glog.InfoExtln("维护工单A", "Actendtime:", Actendtime)
							pm.Actendtime = utils.TimeFormat(Actendtime, "yyyyMMddHHmmss")
						}
					}

					pm.Mainttype = task.PmService.Mainttype
					pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
					pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
					err = pm.Add()
					if err != nil {
						continue
					}
					me := new(models.PmServiceAttrlst)
					me.Finr = task.PmService.Finr
					me.Mainserviceid = task.PmService.Mainserviceid
					data, err := me.SelectAll()
					if err != nil {
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(models.PmWoAttrlst)
						at.Finr = v.Finr
						at.Descr = v.Descr
						at.Mainservicenr = v.Mainserviceid
						at.Maintwoid = woid
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.Paravalue = v.Paravalue
						at.Attrnr = v.Attrnr
						at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						err := at.Add()
						if err != nil {
							continue
						}
					}
				}
			case "B":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()
				dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.Finr, "pm_service")
				ok := dao.IsWorkDate(today)
				if !ok{
					continue
				}

				//逻辑：起始时间+间隔时间，
				t1 := utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
				//判断是否已经生成了维护工单，如果生成了，跳过
				pms := new(models.PmWo)
				pms.Finr = task.PmService.Finr
				pms.Mainservicenr = task.PmService.Mainserviceid
				pms.Assetid = task.PmAsset.Assetid
				tem, err := pms.SelectPmWoOne()
				if err != nil {
					glog.InfoExtln("维护工单B", "err:", err)
					continue
				}
				glog.InfoExtln("维护工单B", "tem:", tem)
				time2, _ := utils.TimeParse(tem.Actbegtime)
				time1, _ := utils.TimeParse(t1)
				timelen := int(time1.Unix()) - int(time2.Unix())
				timeunit := task.PmService.Duehourinterval

				glog.InfoExtln("维护工单B", "Mainservicenr:", task.PmService.Mainserviceid)
				glog.InfoExtln("维护工单B", "tem.Actbegtime:", tem.Actbegtime)
				glog.InfoExtln("维护工单B", "timelen:", timelen)
				glog.InfoExtln("维护工单B", "timeunit:", timeunit)
				if (timelen - timeunit*3600) > 0 {

					snr := new(models.Snrtab)
					snr.Finr = 100
					//生成ID
					woid, err := snr.GetNextSnr("WOID")
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						continue
					}

					//查询当天是否是工作日,如果是跳过
					engine := db.Eloquent.Master()
					session := engine.NewSession()
					defer session.Close()
					dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.Finr, "pm_service")
					res := dao.IsWorkDate(today)
					if !res{
						continue
					}

					//符合逻辑生成维护工单
					pm := new(models.PmWo)
					pm.Finr = task.PmService.Finr
					pm.Maintwoid = woid
					pm.Mainservicenr = task.PmService.Mainserviceid
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.Assetid = task.PmAsset.Assetid
					pm.Plbegdat = utils.TimeFormat(time.Now(), "yyyyMMdd")
					timeNow := time.Now()
					pm.Schedbegtime = utils.TimeFormat(timeNow, "yyyyMMddHHmmss")
					//计算结束时间
					endtime := timeNow.Add(time.Duration(timeunit)*time.Hour)
					glog.InfoExtln("维护工单B", "timeunit:", timeunit)
					pm.Schedendtime = utils.TimeFormat(endtime, "yyyyMMddHHmmss")
					pm.Actbegtime = utils.TimeFormat(timeNow, "yyyyMMddHHmmss")
					pm.Actendtime = utils.TimeFormat(endtime, "yyyyMMddHHmmss")
					pm.Mainttype = task.PmService.Mainttype
					pm.Credatuz = utils.TimeFormat(timeNow, "yyyyMMddHHmmss")
					pm.Lastmodif = utils.TimeFormat(timeNow, "yyyyMMddHHmmss")
					err = pm.Add()
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						continue
					}
					me := new(models.PmServiceAttrlst)
					me.Finr = task.PmService.Finr
					me.Mainserviceid = task.PmService.Mainserviceid
					data, err := me.SelectAll()
					if err != nil {
						glog.InfoExtln("维护工单B", "err:", err)
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(models.PmWoAttrlst)
						at.Finr = v.Finr
						at.Descr = v.Descr
						at.Mainservicenr = v.Mainserviceid
						at.Maintwoid = woid
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.Paravalue = v.Paravalue
						at.Attrnr = v.Attrnr
						at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						err := at.Add()
						if err != nil {
							glog.InfoExtln("维护工单B", "err:", err)
							continue
						}
					}
				}
			case "C":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()
				dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.Finr, "pm_service")
				ok := dao.IsWorkDate(today)
				if !ok{
					continue
				}
				//逻辑：仪表值
				//第一步：查询资产阈值表，判断是否是触发状态
				pma := new(models.PmAssetKpi)
				pma.Finr = task.PmAsset.Finr
				pma.Mainserviceid = utils.ValueToString(task.PmService.Mainserviceid, "")
				info, err := pma.SelectAll()
				if err != nil {
					continue
				}
				for _, pmaInfo := range info {
					switch pmaInfo.Kpitype {
					case 1:
						if pmaInfo.Triggerstatus == 1 {
							continue
						}
						if pmaInfo.Thresholdval < pmaInfo.Actualval {
							continue
						}

						//第二步：生成维护工单，
						//逻辑：根据调度时间维护
						snr := new(models.Snrtab)
						snr.Finr = 100
						//生成ID
						woid, err := snr.GetNextSnr("WOID")
						log.Printf("流水号id:%v", woid)
						if err != nil {
							return
						}
						//符合逻辑生成维护工单
						pm := new(models.PmWo)
						pm.Finr = task.PmService.Finr
						pm.Maintwoid = woid
						pm.Mainservicenr = task.PmService.Mainserviceid
						pm.Descr = task.PmService.Descr
						pm.Status = 26
						pm.Priority = task.PmService.Priority
						pm.Assetid = task.PmAsset.Assetid
						pm.Plbegdat = utils.TimeFormat(time.Now(), "yyyyMMdd")
						pm.Schedbegtime = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						timenow := utils.ValueToString(task.PmService.Maintimelen, "")
						m, _ := time.ParseDuration(timenow + "h")
						pm.Schedendtime = utils.TimeFormat(time.Now().Add(m), "yyyyMMddHHmmss")
						pm.Actbegtime = pm.Schedbegtime
						pm.Actendtime = pm.Schedendtime
						pm.Mainttype = task.PmService.Mainttype
						pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						err = pm.Add()
						if err != nil {
							continue
						}
						me := new(models.PmServiceAttrlst)
						me.Finr = task.PmService.Finr
						me.Mainserviceid = task.PmService.Mainserviceid
						data, err := me.SelectAll()
						if err != nil {
							continue
						}
						//生成属性
						for _, v := range data {
							at := new(models.PmWoAttrlst)
							at.Finr = v.Finr
							at.Descr = v.Descr
							at.Mainservicenr = v.Mainserviceid
							at.Maintwoid = woid
							at.Pos = v.Pos
							at.Parameter = v.Parameter
							at.Paravalue = v.Paravalue
							at.Attrnr = v.Attrnr
							at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
							at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
							err := at.Add()
							if err != nil {
								continue
							}
						}
						//第三步：锁定触发器状态
						pmu := new(models.PmAssetKpi)
						pmu.Finr = 100
						pmu.Triggerstatus = 1
						pmu.Assetid = utils.ValueToString(task.PmAsset.Assetid, "")
						err = pma.Update()
						if err != nil {
							continue
						}
					case 2:
						if pmaInfo.Counterval < pmaInfo.Countercycleval {
							continue
						}
						//第二步：生成维护工单，
						//逻辑：根据调度时间维护
						snr := new(models.Snrtab)
						snr.Finr = 100
						//生成ID
						woid, err := snr.GetNextSnr("WOID")
						log.Printf("流水号id:%v", woid)
						if err != nil {
							return
						}
						//符合逻辑生成维护工单
						pm := new(models.PmWo)
						pm.Finr = task.PmService.Finr
						pm.Maintwoid = woid
						pm.Mainservicenr = task.PmService.Mainserviceid
						pm.Descr = task.PmService.Descr
						pm.Status = 26
						pm.Priority = task.PmService.Priority
						pm.Assetid = task.PmAsset.Assetid
						pm.Plbegdat = utils.TimeFormat(time.Now(), "yyyyMMdd")
						pm.Schedbegtime = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						timenow := utils.ValueToString(task.PmService.Maintimelen, "")
						m, _ := time.ParseDuration(timenow + "h")
						pm.Schedendtime = utils.TimeFormat(time.Now().Add(m), "yyyyMMddHHmmss")
						pm.Actbegtime = pm.Schedbegtime
						pm.Actendtime = pm.Schedendtime
						pm.Mainttype = task.PmService.Mainttype
						pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						err = pm.Add()
						if err != nil {
							continue
						}
						me := new(models.PmServiceAttrlst)
						me.Finr = task.PmService.Finr
						me.Mainserviceid = task.PmService.Mainserviceid
						data, err := me.SelectAll()
						if err != nil {
							continue
						}
						//生成属性
						for _, v := range data {
							at := new(models.PmWoAttrlst)
							at.Finr = v.Finr
							at.Descr = v.Descr
							at.Mainservicenr = v.Mainserviceid
							at.Maintwoid = woid
							at.Pos = v.Pos
							at.Parameter = v.Parameter
							at.Paravalue = v.Paravalue
							at.Attrnr = v.Attrnr
							at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
							at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
							err := at.Add()
							if err != nil {
								continue
							}
						}
						//第三步：计数清零
						pmu := new(models.PmAssetKpi)
						pmu.Finr = 100
						pmu.Countercycleval = 1
						pmu.Assetid = utils.ValueToString(task.PmAsset.Assetid, "")
						err = pma.Update()
						if err != nil {
							continue
						}
					}
				}

			case "D":
				today := utils.TimeFormat(time.Now(), "yyyyMMdd")
				//查询当天是否是工作日,如果是跳过
				engine := db.Eloquent.Master()
				session := engine.NewSession()
				defer session.Close()
				dao := dal.NewWorkCalendarLstDAO(session, task.PmAsset.Finr, "pm_service")
				ok := dao.IsWorkDate(today)
				if !ok{
					continue
				}
				//逻辑：起始时间+间隔时间，
				//判断是否已经生成了维护工单，如果生成了，跳过
				pms := new(models.PmWo)
				pms.Finr = task.PmService.Finr
				pms.Mainservicenr = task.PmService.Mainserviceid
				pms.Assetid = task.PmAsset.Assetid
				tem, err := pms.SelectPmWoOne()
				if err != nil {
					continue
				}
				time2, _ := utils.TimeParse(tem.Actbegtime)
				time1, _ := utils.TimeParseyyyyMMdd(today)
				timelen := int(time1.Unix()) - int(time2.Unix())
				if err != nil {
					continue
				}
				if timelen >= 0 {
					//逻辑：根据调度时间维护
					snr := new(models.Snrtab)
					snr.Finr = 100
					//生成ID
					woid, err := snr.GetNextSnr("WOID")
					log.Printf("流水号id:%v", woid)
					if err != nil {
						return
					}
					//符合逻辑生成维护工单
					pm := new(models.PmWo)
					pm.Finr = task.PmService.Finr
					pm.Maintwoid = woid
					pm.Mainservicenr = task.PmService.Mainserviceid
					pm.Descr = task.PmService.Descr
					pm.Status = 26
					pm.Priority = task.PmService.Priority
					pm.Assetid = task.PmAsset.Assetid
					pm.Plbegdat = utils.TimeFormat(time.Now(), "yyyyMMdd")
					pm.Schedbegtime = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
					timenow := utils.ValueToString(task.PmService.Maintimelen, "")
					m, _ := time.ParseDuration(timenow + "h")
					pm.Schedendtime = utils.TimeFormat(time.Now().Add(m), "yyyyMMddHHmmss")
					pm.Actbegtime = pm.Schedbegtime
					pm.Actendtime = pm.Schedendtime
					pm.Mainttype = task.PmService.Mainttype
					pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
					pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
					err = pm.Add()
					if err != nil {
						continue
					}
					me := new(models.PmServiceAttrlst)
					me.Finr = task.PmService.Finr
					me.Mainserviceid = task.PmService.Mainserviceid
					data, err := me.SelectAll()
					if err != nil {
						continue
					}
					//生成属性
					for _, v := range data {
						at := new(models.PmWoAttrlst)
						at.Finr = v.Finr
						at.Descr = v.Descr
						at.Mainservicenr = v.Mainserviceid
						at.Maintwoid = woid
						at.Pos = v.Pos
						at.Parameter = v.Parameter
						at.Paravalue = v.Paravalue
						at.Attrnr = v.Attrnr
						at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
						err := at.Add()
						if err != nil {
							continue
						}
					}
				}

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