package Device

import (
	"Cold_Data/conf"
	"Cold_Data/lib"
	"Cold_Data/logs"
	"encoding/json"
	"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"
	"strings"
	"time"
)

// 模板
type Device struct {
	T_sn              string    `orm:"pk;size(256);"`            // 设备序列号
	T_pid             int       `orm:"index;size(256);"`         // Account.Company 绑定公司
	T_devName         string    `orm:"size(256);"`               // 设备名称  20字
	T_protocol        int       `orm:"size(2);default(3)"`       // 冷链通讯协议 1 :1.0协议   2 :2.0协议    3 :3.0协议
	T_mqttid          string    `orm:"size(256);"`               // MQTT 服务ID
	T_VerifyTime      time.Time `orm:"type(timestamp);"`         // 验证时间
	T_CalibrationTime time.Time `orm:"type(timestamp);"`         // 校准时间
	T_PatrolTime      time.Time `orm:"type(timestamp);"`         // 巡检时间
	T_ist             int       `orm:"size(2);default(1)"`       // 温度   1开启   2关闭
	T_ish             int       `orm:"size(2);default(1)"`       // 湿度   1开启   2关闭
	T_State           int       `orm:"index;size(2);default(1)"` // 0 屏蔽   1 正常  （屏蔽后 只有内部管理员才能看到，用户 输入SN\名称 搜索时 也能看到）

	// 设备同步参数
	T_Dattery  int    `orm:"size(4);"`                 // 电量       ：设备实时状态推送
	T_Site     string `orm:"size(200);"`               // GPS       ：实时数据  记录数据
	T_monitor  int    `orm:"index;size(2);"`           // 监控状态 0 未监控 1 监控  停止记录     ：记录数据   上下线(=0)
	T_online   int    `orm:"index;size(2);default(0)"` // 在线状态 0 未启用  1 在线  2 static/     ：上下线  消息
	T_online_s int    `orm:"index;size(2);default(0)"` // 在线状态-备用  0 未启用  1 在线  2 离线     ：上下线

	// 硬件信息
	T_model string `orm:"size(200);"` // KF200BG  设备型号
	T_sver  string `orm:"size(200);"` // "1.0.0",//软件版本
	T_hver  string `orm:"size(200);"` // "1.0.0",//硬件版本
	T_imei  string `orm:"size(200);"` // "867387060327718",//模组imei
	T_iccid string `orm:"size(200);"` // "89860477102170049750",//sim卡号
	T_rssi  string `orm:"size(200);"` // "80",//信号强度           ：设备实时状态推送

	CreateTime time.Time `orm:"column(create_time);type(timestamp);auto_now_add"` //auto_now_add 第一次保存时才设置时间
	UpdateTime time.Time `orm:"column(update_time);type(timestamp);auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
}

type Device_task struct {
	T_sn   string
	T_task string
}

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

var redisCache_Device cache.Cache

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

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

// ---------------- Redis -------------------
// Redis_Set(m.T_sn,m) // Redis 更新缓存
func Redis_Set(key string, r Device) (err error) {
	//json序列化
	str, err := json.Marshal(r)
	if err != nil {
		logs.PrintlnError("Redis_Set", err)
		return
	}

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

// if r,is :=Redis_Get(T_sn);is{
// return r,nil
// }
func Redis_Get(key string) (r Device, is bool) {
	if redisCache_Device.IsExist(key) {
		//println("找到key:",key)
		v := redisCache_Device.Get(key)
		if v == nil {
			return Device{}, false
		}
		json.Unmarshal(v.([]byte), &r)
		return r, true
	}
	//println("没有 找到key:",key)
	return Device{}, false
}

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

// 获取 ById
func Read_Device_ByT_sn(T_sn string) (r Device, err error) {
	if r, is := Redis_Get(T_sn); is {
		//println("Redis_Get  OK")
		return r, nil
	}
	//println("没有 Redis_Get SN")
	o := orm.NewOrm()
	r = Device{T_sn: T_sn, T_State: 1}
	err = o.Read(&r, "T_sn", "T_State") // o.Read(&r,"Tokey") 如果不是 主键 就得指定字段名
	if err != nil {
		logs.Println("Read_Device_ByT_sn", err)
		return r, err
	}
	Redis_Set(r.T_sn, r) // Redis 更新缓存
	return r, err
}

// 设备类型统计
func Hande_device_sensor_type() {
	o := orm.NewOrm()
	var maps orm2.ParamsList
	o.Raw("SELECT ID FROM device_sensor_type WHERE t_view = 1").ValuesFlat(&maps)
	data, _ := json.Marshal(maps)
	conf.KF = string(data)
	fmt.Println(conf.KF)
	conf.KF = strings.Replace(conf.KF, "[", "(", -1)
	conf.KF = strings.Replace(conf.KF, "]", ")", -1)
	conf.KF = strings.Replace(conf.KF, "\"", "", -1)
	println("conf.KF:", conf.KF)

	o.Raw("SELECT ID FROM device_sensor_type WHERE t_view = 2").ValuesFlat(&maps)
	data, _ = json.Marshal(maps)
	conf.YD = string(data)
	fmt.Println(conf.YD)
	conf.YD = strings.Replace(conf.YD, "[", "(", -1)
	conf.YD = strings.Replace(conf.YD, "]", ")", -1)
	conf.YD = strings.Replace(conf.YD, "\"", "", -1)
	println("conf.KF:", conf.YD)
}

// 获取 ById
func Read_Device_设备总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	o.Raw("SELECT COUNT(1) FROM device_sensor WHERE t_pid = ? AND t__state = 1 ", t_pid).Values(&maps)

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

// 获取 ById
func Read_Device_设备离线总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	o.Raw("SELECT COUNT(1) FROM device_sensor WHERE t_pid = ? AND t_type IN "+conf.YD+" AND t__state = 1 AND( t_online <> 1 OR t_online_s <> 1 )", t_pid).Values(&maps)

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

// 获取 ById
func Read_Device_设备监控总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	o.Raw("SELECT COUNT(1) FROM device_sensor WHERE t_pid = ? AND t_type IN "+conf.YD+" AND t__state = 1 AND t_monitor = 1", t_pid).Values(&maps)

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

// 获取 ById
func Read_Device_库房总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	o.Raw("SELECT COUNT(1) FROM device_sensor WHERE t_pid = ? AND t_type IN"+conf.KF+" AND t__state = 1", t_pid).Values(&maps)

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

// 获取 ById
func Read_Device_移动总数(t_pid int) int {

	o := orm.NewOrm()
	var maps []orm2.Params
	o.Raw("SELECT COUNT(1) FROM device_sensor WHERE t_pid = ? AND t_type IN"+conf.YD+" AND t__state = 1", t_pid).Values(&maps)

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