package jobs

import (
	sysModel "cold-delivery/app/admin/model"
	"cold-delivery/common/global"
	"cold-delivery/common/nats/nats_server"
	"cold-delivery/db"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	log "gogs.baozhida.cn/zoie/OAuth-core/logger"
	"sort"
	"time"
)

// 需要将定义的struct 添加到字典中；
// 字典 key 可以配置到 自动任务 调用目标 中；
func InitJob() {
	jobList = map[string]JobsExec{
		//"ExamplesOne":     ExamplesOne{},
		"CountIceRaftRecordFreezeDuration": CountIceRaftRecordFreezeDuration{},
		"UpdateCoolerBoxMonitorStatus":     UpdateCoolerBoxMonitorStatus{},
		"CountIceRaftRecordForColdNow":     CountIceRaftRecordForColdNow{},
		"CountCoolerBoxForColdNow":         CountCoolerBoxForColdNow{},
		// ...
	}
}

// 新添加的job 必须按照以下格式定义，并实现Exec函数
type ExamplesOne struct {
}

func (t ExamplesOne) Exec(arg interface{}) error {
	str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success"
	// TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string)；请根据对应的类型进行转化；
	switch arg.(type) {

	case string:
		if arg.(string) != "" {
			fmt.Println("string", arg.(string))
			fmt.Println(str, arg.(string))
		} else {
			fmt.Println("arg is nil")
			fmt.Println(str, "arg is nil")
		}
		break
	}

	return nil
}

// CountIceRaftRecordFreezeDuration 统计冰排冷冻时长
type CountIceRaftRecordFreezeDuration struct {
}

// UpdateCoolerBoxMonitorStatus 更新保温箱监控状态
type UpdateCoolerBoxMonitorStatus struct {
}

// CountIceRaftRecordForColdNow 统计冰排释冷时长
type CountIceRaftRecordForColdNow struct {
}

// CountCoolerBoxForColdNow 统计保温箱遇冷时长
type CountCoolerBoxForColdNow struct {
}

// Exec 统计冰排冷冻时长
func (t CountIceRaftRecordFreezeDuration) Exec(arg interface{}) error {

	iceRaftRecordList := make([]sysModel.IceRaftRecord, 0)
	// GetOrm 获取orm连接
	orm, _ := db.GetOrm(&gin.Context{})

	err := orm.Where("status = ? or status = ? ", sysModel.IceRaftRecordStatusFreezing, sysModel.IceRaftRecordStatusWaitUse).
		Find(&iceRaftRecordList).Error
	if err != nil {
		log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	//冰排统计时长
	for _, record := range iceRaftRecordList {
		sort.Slice(record.FreezeClaim, func(i, j int) bool {
			return record.FreezeClaim[i] < record.FreezeClaim[j]
		})
		inTime := record.InStorageTime.Local()
		//if inTime.Add(time.Hour * time.Duration(record.FreezeClaim)).After(time.Now()) {
		if inTime.Add(time.Duration(record.FreezeClaim[0] * float64(time.Hour))).After(time.Now()) {
			// 未达到冷冻时长 不修改状态 只修改时间
			record.FreezeDuration = float64(int(time.Now().Sub(inTime).Minutes()))
		} else {
			record.FreezeDuration = float64(int(time.Now().Sub(inTime).Minutes()))
			record.Status = sysModel.IceRaftRecordStatusWaitUse
		}

		if err := orm.Save(&record).Error; err != nil {
			log.Errorf("db error: %s", err)
			return global.UpdateFailedErr
		}

	}
	return nil
}

// Exec 更新保温箱监控状态
func (t UpdateCoolerBoxMonitorStatus) Exec(arg interface{}) error {
	// GetOrm 获取orm连接
	orm, _ := db.GetOrm(&gin.Context{})
	var coolerBox []sysModel.CoolerBox
	err := orm.Model(&sysModel.CoolerBox{}).Find(&coolerBox).Error
	if err != nil {
		log.Errorf("获取保温箱状态失败: %s", err)
		return global.GetFailedErr
	}
	for i, _ := range coolerBox {
		data, _ := nats_server.Read_Device_ByT_sn(coolerBox[i].Sn)
		if len(data.T_sn) != 0 {
			//只查询设备在线并且处于监控状态下的设备
			if data.T_monitor != coolerBox[i].MonitorStatus {
				err := orm.Model(&sysModel.CoolerBox{}).Where("id = ?", coolerBox[i].Id).Update("monitor_status", data.T_monitor).Error
				if err != nil {
					log.Errorf("更新保温箱监控状态失败: %s", err)
					return global.UpdateFailedErr
				}
			}
		} else {
			if coolerBox[i].MonitorStatus != 4 {
				err := orm.Model(&sysModel.CoolerBox{}).Where("id = ?", coolerBox[i].Id).Update("monitor_status", 4).Error
				if err != nil {
					log.Errorf("更新保温箱监控状态失败: %s", err)
					return global.UpdateFailedErr
				}
			}
		}
	}
	return nil
}

// Exec 统计冰排释冷时长
func (t CountIceRaftRecordForColdNow) Exec(arg interface{}) error {
	// GetOrm 获取orm连接
	orm, _ := db.GetOrm(&gin.Context{})

	var iceRaftRecordList []sysModel.IceRaftRecord

	err := orm.Where("status = ?", sysModel.IceRaftRecordReleasedInTheCold).
		Or("status = ?", sysModel.IceRaftRecordReleasedInTheColdEnd).
		Find(&iceRaftRecordList).Error
	if err != nil {
		log.Errorf("db 查询冰排记录失败: %s", err)
		return errors.New("查询冰排记录失败")
	}
	//冰排释冷时长
	for _, record := range iceRaftRecordList {
		inTime := record.StartIceColdTime.Local()
		var iceRaft sysModel.IceRaft
		err = orm.Where("id = ?", record.IceRaftId).First(&iceRaft).Error
		if err != nil {
			log.Errorf("冰排不存在: %s", err)
			//return errors.New("查询冰排失败")
		}
		if inTime.Add(time.Duration(iceRaft.ForColdTime * float64(time.Hour))).After(time.Now()) {
			// 未达到冷冻时长 不修改状态 只修改时间
			record.ForColdTimeActual = time.Now().Sub(inTime).Minutes()
		} else {
			record.ForColdTimeActual = time.Now().Sub(inTime).Minutes()
			record.Status = sysModel.IceRaftRecordReleasedInTheColdEnd
		}
		if err = orm.Save(&record).Error; err != nil {
			log.Errorf("更新冰排释冷时间失败: %s", err)
			fmt.Println("===================================更新冰排释冷时间失败===================================", err)
			return global.UpdateFailedErr
		}
	}
	return nil
}

// Exec 统计保温箱遇冷时长
func (t CountCoolerBoxForColdNow) Exec(arg interface{}) error {
	CoolerBoxListRecord := make([]sysModel.CoolerBoxRecord, 0)
	// GetOrm 获取orm连接
	orm, _ := db.GetOrm(&gin.Context{})

	err := orm.Where("status = ?", 1).
		Find(&CoolerBoxListRecord).Error
	if err != nil {
		log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	//冰排释冷时长
	for _, record := range CoolerBoxListRecord {
		inTime := record.CoolerBoxStarTime.String()
		if len(inTime) != 0 {
			var coolerBox sysModel.CoolerBox
			var sprintf string
			err := orm.Where("id = ?", record.CoolerBoxId).First(&coolerBox).Error
			if err != nil {
				log.Errorf("db error: %s", err)
				return global.GetFailedErr
			}
			if (coolerBox.UseStatus == 1 || coolerBox.UseStatus == 3) && len(record.CoolerUserTime.String()) == 0 {
				sub := time.Now().Sub(record.CoolerBoxStarTime.Local())
				hours := int(sub.Hours())
				minutes := int(sub.Minutes()) % 60
				sprintf = fmt.Sprintf("%dh%dm\n", hours, minutes)
				if record.CoolerBoxStarTime.Local().Add(time.Duration(coolerBox.ForColdCoolerTime * float64(time.Hour))).After(time.Now()) {
					// 未达到冷冻时长 不修改状态 只修改时间
					record.ForColdDuration = sprintf
				} else {
					record.ForColdDuration = sprintf
					coolerBox.UseStatus = 3 //遇冷结束
				}
				err = orm.Save(&coolerBox).Error
				err = orm.Save(&record).Error
				if err := orm.Save(&record).Error; err != nil {
					log.Errorf("db error: %s", err)
					return global.UpdateFailedErr
				}
			}

		}
	}
	return nil
}
