package service

import (
	"database/sql"
	"fmt"
	"strconv"
	"time"
	"ydMonitoring/config"
	"ydMonitoring/databases"
	"ydMonitoring/util"
)

var (
	thresholdTemperature,
	thresholdHumidity float64
	// DateFormat 格式化时间字符串
	DateFormat = "2006-01-02 15:04:05"
	//EquipmentMonitoringTime uint64
	errRangeTime int
)

func init() {
	thresholdTemperature = config.Config.GetFloat64("monitoring.temperature")
	thresholdHumidity = config.Config.GetFloat64("monitoring.humidity")
	errRangeTime = config.Config.GetInt("monitoring.errRangeTime")
	//EquipmentMonitoringTime = config.Config.GetUint64("monitoring.equipmentMonitoringTime")

}

type Device struct {
	Tsn       string      //sn
	TDevName  string      //设备名称
	TSaveTime int64       //设备保存时间间隔
	TSensors  [][2]string //设备探头
	TTasks    [][2]string //任务列表
}
type DeviceSensor struct {
	Tsn   string //sn
	TId   string //探头
	TPid  string //设备公司id
	TName string //设备名称
}

type Data struct {
	Tt    float64
	Trh   float64
	TTime time.Time
}

var (
	thresholdTt,
	thresholdTrh float64
	recordTime int
)

func init() {
	recordTime = config.Config.GetInt("monitoring.equipmentHour")
}

// []string{"BX200GSE", "MD100", "MD200G", "BX100", "KF100", "MD300G"}
// EquipmentMonitoring2 监控设备v2
func EquipmentMonitoring2() {
	//1.获取所有设备表
	sqlStatement := "select t_sn,t_dev_name from device where t__state = 1 and t_pid !=2 and (t_model = 'BX200GSE' OR t_model = 'MD100' OR t_model LIKE 'MD200G' OR t_model LIKE 'BX100' OR t_model LIKE 'KF100' OR t_model LIKE 'MD300G') "
	rows, _ := databases.Db.Query(sqlStatement)
	devices := make([]Device, 0)
	var sn, devName string
	for rows.Next() {
		rows.Scan(&sn, &devName)
		devices = append(devices, Device{Tsn: sn, TDevName: devName, TSensors: [][2]string{}, TTasks: [][2]string{}})
	}

	//fmt.Println("查询得到设备：", devices)
	//fmt.Println("查询得到设备：", len(devices))
	//HandleTsn(devices)
	DataCaps(devices)
}

// 处理sn
func HandleTsn(devices []Device) {

	//查询所有设备探头
	var sensorId, sensorName string
	for i, v := range devices {
		sqlStatement := fmt.Sprintf("select t_id,t_name from device_sensor where t__state = 1 AND t_sn = '%s'", v.Tsn)
		rows, err := databases.Db.Query(sqlStatement)
		if err != nil {
			fmt.Println("查询", v.Tsn, "设备探头出错：", err.Error())
		}
		for rows.Next() {
			rows.Scan(&sensorId, &sensorName)
			// [设备名称,探头id,探头名称]
			v.TSensors = append(v.TSensors, [2]string{sensorId, sensorName})
		}
		devices[i] = v
	}
	fmt.Println("查询得到设备探头：", devices)

	//查询所有保存时间
	var tSaveT int64
	var devName any
	for i := 0; i < len(devices); i++ {
		sqlStatement := fmt.Sprintf("select t_name,t_save_t from device_parameter where t_sn = '%s' order by ID desc,update_time desc limit 1", devices[i].Tsn)
		row := databases.Db.QueryRow(sqlStatement)
		row.Scan(&devName, &tSaveT)
		devices[i].TSaveTime = tSaveT
		devices[i].TDevName = fmt.Sprintf("%v", devName)
		if tSaveT == 0 {
			util.SendWarning(devices[i].Tsn, -1, devices[i].TDevName, "", "设备保存时间未设置！")
			continue
		}
		fmt.Println("设备：", devices[i].Tsn, "保存时间：", devices[i].TSaveTime)
	}

	//查询是否存在执行计划，判断sn 是否为移动设备；
	var now = time.Now()
	var lastTowHours = now.Add(time.Hour * -time.Duration(recordTime))
	var start, end string
	for i, v := range devices {
		sqlStatement := fmt.Sprintf("select t__ut_start,t__ut_end from device_task where t_sn = '%s' and t__ut_end >= '%s'", v.Tsn, lastTowHours.Format(DateFormat))
		rows, err := databases.Db.Query(sqlStatement)

		if err != nil {
			fmt.Println(err)
		}

		//如果存在数据则表示是移动端
		for rows.Next() {
			rows.Scan(&start, &end)
			v.TTasks = append(v.TTasks, [2]string{start, end})
		}
		devices[i] = v
	}
	fmt.Println("查询得到设备任务：", devices)

	//公共的sql模板
	commonsStatement := "SELECT t_t,t_rh,DATE_FORMAT(t_time,'%%Y-%%m-%%d %%H:%%i:%%s') as t_time FROM z_device_data_%s WHERE t_id = '%s' AND t_time BETWEEN '%s' AND '%s' ORDER BY t_time DESC"

	var interval int64
	for _, v := range devices {

		//存在任务
		if len(v.TTasks) != 0 {
			for _, task := range v.TTasks {

				//计算时间差
				s, _ := time.Parse(DateFormat, task[0])
				e, _ := time.Parse(DateFormat, task[1])
				interval = e.Unix() - s.Unix()

				//循环查询各探头
				for _, sensor := range v.TSensors {
					sqlT := fmt.Sprintf(commonsStatement, v.Tsn, sensor[0], task[0], task[1])
					fmt.Println(sqlT)
					rows, err := databases.Db.Query(sqlT)
					if err != nil {
						fmt.Println("SOL查询错误！\t", err.Error())
					}
					handleDeviceData(v, sensor, interval, task[0], task[1], rows)
				}
			}
			continue
		}

		//不存在任务
		interval = now.Unix() - lastTowHours.Unix()
		for _, sensor := range v.TSensors {
			rows, err := databases.Db.Query(fmt.Sprintf(commonsStatement, v.Tsn, sensor[0], lastTowHours.Format(DateFormat), now.Format(DateFormat)))
			if err != nil {
				fmt.Println("SOL查询错误！\t", err.Error())
			}
			handleDeviceData(v, sensor, interval, lastTowHours.Format(DateFormat), now.Format(DateFormat), rows)
		}
	}
}

// 处理数据
func handleDeviceData(d Device, sensor [2]string, interval int64, start, end string, rows *sql.Rows) {

	var sensorId, _ = strconv.ParseInt(sensor[0], 10, 64)
	fmt.Println("设备sn：", d.Tsn, "-", sensorId, " 任务时间：", start, end)
	//读取数据
	datas := make([]Data, 0)
	var t, rh float64
	var tTime string
	for rows.Next() {
		rows.Scan(&t, &rh, &tTime)
		ttime, _ := time.Parse(DateFormat, tTime)
		datas = append(datas, Data{t, rh, ttime})
	}
	fmt.Println("查询得到设备", d.Tsn, "数据：", len(datas), "最少条数：", d.TSaveTime, interval/d.TSaveTime, "条\t设备保存时间：")
	//
	////时间内记录数小于应该保存的记录数，发出预警
	//if d.TSaveTime != 0 {
	//	if int64(len(datas)) < (interval / d.TSaveTime) {
	//		util.SendWarning(d.Tsn, int(sensorId), d.TDevName, sensor[1], fmt.Sprintf("设备[%s]探头[%d]   [%s~%s]超出保存时间范围，缺少数据[%d]条", d.Tsn, sensorId, start, end, interval/d.TSaveTime-int64(len(datas))))
	//	}
	//}

	//处理数据
	var current, next Data
	for i := 0; i < len(datas)-1; i++ {
		current = datas[i]
		next = datas[i+1]

		//不在保存时间范围内
		if d.TSaveTime != 0 {
			interval := current.TTime.Unix() - next.TTime.Unix() - d.TSaveTime
			if interval >= d.TSaveTime {
				util.SendWarning(d.Tsn, int(sensorId), d.TDevName, sensor[1], fmt.Sprintf("设备[%s]探头[%d]   [%s~%s]超出保存时间范围 [%d] 上传时间间隔[%d]，缺少数据[%d]条", d.Tsn, sensorId, next.TTime.Format(DateFormat), current.TTime.Format(DateFormat), interval, d.TSaveTime, interval/d.TSaveTime))
			}
		}

		//温度
		temperatureInterval := current.Tt - next.Tt
		if temperatureInterval > thresholdTemperature {
			util.SendWarning(d.Tsn, int(sensorId), d.TDevName, sensor[1], fmt.Sprintf("设备[%s]探头[%d]   [%s~%s]超出温度变化范围，变化差值[%.2f]", d.Tsn, sensorId, next.TTime.Format(DateFormat), current.TTime.Format(DateFormat), temperatureInterval))
		}

		//湿度
		humidityInterval := current.Trh - next.Trh
		if humidityInterval > thresholdHumidity {
			util.SendWarning(d.Tsn, int(sensorId), d.TDevName, sensor[1], fmt.Sprintf("设备[%s]探头[%d]   [%s~%s]超出湿度变化范围，变化差值[%.2f]", d.Tsn, sensorId, next.TTime.Format(DateFormat), current.TTime.Format(DateFormat), humidityInterval))
		}
	}
}
