package models

import (
	"encoding/json"
	"errors"
	"time"

	"gorm.io/datatypes"
)

// SensorType 定义了 SensorData 记录中 Data 字段的整体类型
type SensorType string

const (
	SensorTypeSignalMetrics SensorType = "信号强度" // 信号强度
	SensorTypeBatteryLevel  SensorType = "电池电量" // 电池电量
	SensorTypeTemperature   SensorType = "温度"   // 温度
	SensorTypeHumidity      SensorType = "湿度"   // 湿度
	SensorTypeWeight        SensorType = "重量"   // 重量
)

// SignalMetrics 存储信号强度数据
type SignalMetrics struct {
	RssiDbm        int     `json:"rssi_dbm"`        // 绝对信号强度（dBm），受距离、障碍物影响
	SnrDb          float32 `json:"snr_db"`          // 信号与噪声的相对比率（dB），由 RSSI 减去噪声地板（Noise Floor）
	SensitivityDbm int     `json:"sensitivity_dbm"` // 网关的最低检测阈值(dBm)
	MarginDb       int     `json:"margin_db"`       // SNR 相对于接收器灵敏度的余量, Margin = SNR - Sensitivity
}

// BatteryLevel 存储电池电量数据
type BatteryLevel struct {
	BatteryLevelRatio       float32 `json:"battery_level_ratio"`       // 电量剩余百分比(%)
	BatteryLevelUnavailable bool    `json:"battery_level_unavailable"` // 电量数据不可用
	ExternalPower           bool    `json:"external_power"`            // 是否使用外部电源
}

// TemperatureData 存储温度数据
type TemperatureData struct {
	TemperatureCelsius float32 `json:"temperature_celsius"` // 温度值 (摄氏度)
}

// HumidityData 存储湿度数据
type HumidityData struct {
	HumidityPercent float32 `json:"humidity_percent"` // 湿度值 (%)
}

// WeightData 存储重量数据
type WeightData struct {
	WeightKilograms float32 `json:"weight_kilograms"` // 重量值 (公斤)
}

// SensorData 存储所有类型的传感器数据，对应数据库中的 'sensor_data' 表。
type SensorData struct {
	// Time 是数据记录的时间戳，作为复合主键的一部分。
	Time time.Time `gorm:"primaryKey" json:"time"`

	// DeviceID 是传感器的唯一标识符，作为复合主键的另一部分。
	DeviceID uint32 `gorm:"primaryKey" json:"device_id"`

	// AreaControllerID 是上报此数据的区域主控的ID。
	AreaControllerID uint32 `json:"area_controller_id"`

	// SensorType 是传感数据的类型
	SensorType SensorType `gorm:"not null;index" json:"sensor_type"`

	// Data 存储一个或多个传感器读数，格式为 JSON。
	Data datatypes.JSON `gorm:"type:jsonb" json:"data"`
}

func (SensorData) TableName() string {
	return "sensor_data"
}

// ParseData 解析 JSON 数据到一个具体的结构体中。
// 调用方需要传入一个指向目标结构体实例的指针。
func (s *SensorData) ParseData(v interface{}) error {
	if s.Data == nil {
		return errors.New("传感器数据为空，无法解析")
	}
	return json.Unmarshal(s.Data, v)
}
