package Warning

import (
	"Cold_Data/conf"
	"Cold_Data/lib"
	"Cold_Data/logs"
	"fmt"
	"github.com/astaxie/beego/cache"
	_ "github.com/astaxie/beego/cache/redis"
	"github.com/beego/beego/v2/adapter/orm"
	orm2 "github.com/beego/beego/v2/client/orm"
	_ "github.com/go-sql-driver/mysql"
	"strconv"
	"strings"
	"time"
)

type Warning struct {
	Id        int64     `orm:"column(ID);size(11);auto;pk"`
	T_pid     int       `orm:"size(256);null"`        // Account.Company 绑定公司
	T_tp      int       `orm:"size(200);null"`        // 报警类型   ->WarningList
	T_sn      string    `orm:"index;size(256);null"`  // 设备序列号
	T_D_name  string    `orm:"size(256);null"`        // 设备名称
	T_id      int       `orm:"size(200);null"`        // 传感器 ID
	T_DS_name string    `orm:"size(256);null"`        // 传感器名称
	T_Remark  string    `orm:"type(text);null"`       // 采集内容
	T_Ut      time.Time `orm:"type(timestamp);null;"` // 采集时间
	T_fUt     time.Time `orm:"type(timestamp);null;"` // 首次采集时间

	T_Text string `orm:"type(text);null"` // 处理备注
	T_Log  string `orm:"type(text);null"` // 通知日志
	T_Msid int64  `orm:"size(256);null"`  // 消息ID

	T_State    int       `orm:"size(2);default(2)"`                                    // 0 删除   1 不处理   2 已处理   3 未处理
	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
}

// 多字段索引
func (u *Warning) TableIndex() [][]string {
	return [][]string{
		[]string{"T_pid", "T_tp", "T_State"},
	}
}

func (t *Warning) TableName() string {
	return "warning" // 数据库名称   // ************** 替换 FormulaList **************
}

var redisCache_Warning cache.Cache

func init() {
	//注册模型
	orm.RegisterModel(new(Warning))

	config := fmt.Sprintf(`{"key":"%s","conn":"%s","dbNum":"%s","password":"%s"}`,
		"redis_WarningNum", conf.Redis_address, conf.Redis_dbNum, conf.Redis_password)
	logs.Println(config)
	var err error
	redisCache_Warning, err = cache.NewCache("redis", config)
	if err != nil || redisCache_Warning == nil {
		errMsg := "failed to init redis"
		logs.Println(errMsg, err)
	}
}

// ---------------- Redis -------------------
// Redis_Set(m.T_sn,m) // Redis 更新缓存
func Redis_Warning_Set(key string) (err error) {

	err = redisCache_Warning.Put(key, "", 24*time.Hour)
	if err != nil {
		logs.Println("set key:", key)
	}
	return
}

// if r,is :=Redis_Get(T_sn);is{
// return r,nil
// }
func Redis_Warning_Repeat_T_sn_Msid(key string) (is bool) {
	if redisCache_Warning.IsExist(key) {
		//println("找到key:",key)
		return true
	}
	redisCache_Warning.Put(key, "", 1*time.Minute)
	return false
}

// 缓存报警次数     cut 持续秒        (计次，剩余时间s)
func Redis_Warning_Num(key string) (int64, int) {
	if redisCache_Warning.IsExist(key) {
		//logs.Println("Redis_Warning_Num  找到key:", key)
		r := redisCache_Warning.Get(key)
		if r == nil {
			return 0, 0
		}
		value_str := string(r.([]byte))
		value_str_list := strings.Split(value_str, "|")
		if len(value_str_list) != 2 {
			return 0, 0
		}
		logs.Println("value_str_list:", value_str_list) //value_str_list: [[1 1677724222]]
		value_int, _ := strconv.ParseInt(value_str_list[0], 10, 64)
		cut := int(time.Unix(lib.To_int64(value_str_list[1]), 0).Unix() - time.Now().Unix()) // 计算 还剩 s秒时间
		return value_int, cut
	}
	return 0, 0
}

// 缓存报警次数     cut 持续秒        (计次，剩余时间s)
func Redis_Warning_Num_W(key, cuts string) (int64, int) {
	cut, err := strconv.Atoi(cuts)
	if err != nil {
		logs.PrintlnError("Redis_Warning_Num err:", err)
	}

	if redisCache_Warning.IsExist(key) {
		//logs.Println("Redis_Warning_Num  找到key:", key)
		r := redisCache_Warning.Get(key)
		if r == nil {
			goto breakHere // 跳转到标签
		}
		value_str := string(r.([]byte))
		value_str_list := strings.Split(value_str, "|")
		logs.Println("value_str_list:", value_str_list) //value_str_list: [[1 1677724222]]
		if len(value_str_list) != 2 {
			goto breakHere // 跳转到标签
		}
		value_int, _ := strconv.ParseInt(value_str_list[0], 10, 64)
		value_int += 1 // 数量
		//logs.Println("有数据 value_int:", value_int)
		cut = int(time.Unix(lib.To_int64(value_str_list[1]), 0).Unix() - time.Now().Unix()) // 计算 还剩 s秒时间
		redisCache_Warning.Put(key, fmt.Sprintf("%d|%s", value_int, value_str_list[1]), time.Duration(cut)*time.Second)
		logs.Println("Redis_Warning_Num KEY:", key, "->", value_int, "  还剩时间 ->", cut)

		return value_int, cut
	}
breakHere:
	//logs.Println("没有数据 value_int:", 1)
	s, _ := time.ParseDuration(fmt.Sprintf("%ds", cut))
	redisCache_Warning.Put(key, fmt.Sprintf("1|%d", time.Now().Add(s).Unix()), time.Duration(cut)*time.Second)
	logs.Println("Redis_Warning_Num NewKEY:", key, " cut:", cut)
	return 1, cut
}

// 管理员 缓存报警次数
func Redis_WarningToAdmin_Num(key string) bool {
	if redisCache_Warning.IsExist(key) {
		////logs.Println("Redis_Warning_Num  找到key:", key)
		//r := redisCache_Warning.Get(key)
		//value_str := string(r.([]byte))
		//value_int, _ := strconv.ParseInt(value_str, 10, 64)
		//value_int += 1
		////logs.Println("有数据 value_int:", value_int)
		////redisCache_Warning.Put(key, strconv.FormatInt(value_int, 10), 11*time.Minute)
		return false
	}
	//logs.Println("没有数据 value_int:", 1)
	redisCache_Warning.Put(key, "1", 30*time.Minute)
	return true
}

// ---------------- 特殊方法 -------------------

func Read_Warning_库房报警设备数(t_pid int, Wtime string) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(DISTINCT t_sn,t_id) AS COUNT  FROM warning WHERE t__state > 1  AND t_tp IN (1,2,4,5,109) AND " + Wtime + " AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.KF + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT"])
}

func Read_Warning_移动报警设备数(t_pid int, Wtime string) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(DISTINCT t_sn,t_id) AS COUNT  FROM warning WHERE t__state > 1  AND t_tp IN (1,2,4,5,109) AND " + Wtime + " AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.YD + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT"])
}
func Read_Warning_报警设备数(t_pid int, Wtime string) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(DISTINCT t_sn,t_id) AS COUNT  FROM warning WHERE t__state > 1  AND t_tp IN (1,2,4,5,109) AND " + Wtime + " AND t_sn IN (\n\tSELECT\n\t\tt_sn \n\tFROM\n\t\tdevice \n\tWHERE\n\t\tt_pid = ? )"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT"])
}

func Read_Warning_库房报警总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(1) FROM warning WHERE t__state > 1  AND t_tp IN (1,2,4,5,109) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.KF + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT(1)"])
}

func Read_Warning_移动警数总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(1) FROM warning WHERE t__state > 1  AND t_tp IN (1,2,4,5,109) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.YD + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT(1)"])
}

func Read_Warning_库房未处理总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(1) FROM warning WHERE t__state = 3  AND t_tp IN (1,2,4,5,109) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.KF + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT(1)"])
}

func Read_Warning_移动未处理总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(1) FROM warning WHERE t__state = 3  AND t_tp IN (1,2,4,5,109) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.YD + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT(1)"])
}

func Read_Warning_库房设备报警数(t_pid int, Wtime string) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(*) AS COUNT  FROM warning WHERE t__state > 1 AND t_tp IN (1,2,4,5,109) AND " + Wtime + " AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.KF + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT"])
}

func Read_Warning_移动设备报警数(t_pid int, Wtime string) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT COUNT(*) AS COUNT  FROM warning WHERE t__state > 1 AND t_tp IN (1,2,4,5,109)  AND " + Wtime + " AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.YD + ")"
	o.Raw(sql, t_pid).Values(&maps)

	return lib.To_int(maps[0]["COUNT"])
}

func Read_Warning_库房报警类型统计(t_pid int) []orm2.Params {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT t_tp,COUNT(*)  FROM warning WHERE t__state > 1 AND t_tp IN (1,2,4,5,109) AND DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(create_time) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.KF + ") GROUP BY t_tp"
	o.Raw(sql, t_pid).Values(&maps)

	return maps
}
func Read_Warning_移动端报警类型统计(t_pid int) []orm2.Params {

	o := orm.NewOrm()
	var maps []orm2.Params
	sql := "SELECT t_tp,COUNT(*)  FROM warning WHERE t__state > 1 AND t_tp IN (1,2,4,5,109) AND DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(create_time) AND t_sn IN (SELECT DISTINCT t_sn FROM device_sensor WHERE t_pid = ? AND t_type IN " + conf.YD + ") GROUP BY t_tp"
	o.Raw(sql, t_pid).Values(&maps)
	return maps
}
func Read_Warning_探头报警统计(t_pid int) []orm2.Params {
	o := orm.NewOrm()
	var maps []orm2.Params
	sql := fmt.Sprintf("SELECT t__d_s_name, COUNT(*) FROM warning WHERE t_pid = '%v' AND t_tp IN (1,2,4,5,109) AND  DATE(t__ut) = CURDATE() GROUP BY t__d_s_name", t_pid)
	o.Raw(sql).Values(&maps)
	return maps
}

func Read_Warning_日期探头报警统计(t_pid int, Wtime string) []orm2.Params {
	o := orm.NewOrm()
	var maps []orm2.Params
	sql := fmt.Sprintf("SELECT t__d_s_name, COUNT(*) FROM warning WHERE t_pid = '%v' AND t_tp IN (1,2,4,5,109) AND  %v GROUP BY t__d_s_name", t_pid, Wtime)
	o.Raw(sql).Values(&maps)
	return maps
}
