package system

import (
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

type Temperature struct {
	Chip    string  `json:"chip" example:"k10temp" doc:"hwmon chip name; identifies the source (k10temp/coretemp=CPU, amdgpu/nvidia=GPU, nvme=disk)"`
	Label   string  `json:"label" example:"Tctl" doc:"Per-sensor label, or the chip name when the sensor is unlabelled"`
	Celsius float64 `json:"celsius" example:"47.5"`
}

func tempInfo() []Temperature {
	if t := readHwmonTemps("/sys/class/hwmon"); len(t) > 0 {
		return t
	}
	return readThermalZones("/sys/class/thermal")
}

func readThermalZones(root string) []Temperature {
	zones, _ := filepath.Glob(filepath.Join(root, "thermal_zone*"))
	temps := []Temperature{}
	for _, dir := range zones {
		milli, err := strconv.Atoi(readTrim(filepath.Join(dir, "temp")))
		if err != nil {
			continue
		}
		c := float64(milli) / 1000
		if c <= 0 || c >= 150 {
			continue
		}
		name := readTrim(filepath.Join(dir, "type"))
		if name == "" {
			name = filepath.Base(dir)
		}
		temps = append(temps, Temperature{Chip: name, Label: name, Celsius: c})
	}
	return temps
}

func readHwmonTemps(root string) []Temperature {
	chips, _ := filepath.Glob(filepath.Join(root, "hwmon*"))
	temps := []Temperature{}
	for _, dir := range chips {
		chip := readTrim(filepath.Join(dir, "name"))
		inputs, _ := filepath.Glob(filepath.Join(dir, "temp*_input"))
		for _, in := range inputs {
			milli, err := strconv.Atoi(readTrim(in))
			if err != nil {
				continue
			}
			c := float64(milli) / 1000
			if c <= 0 || c >= 150 {
				continue
			}
			label := readTrim(strings.TrimSuffix(in, "_input") + "_label")
			if label == "" {
				label = chip
			}
			temps = append(temps, Temperature{Chip: chip, Label: label, Celsius: c})
		}
	}
	return temps
}

// readTrim reads a sysfs file and trims it; a missing file yields "".
func readTrim(path string) string {
	b, _ := os.ReadFile(path)
	return strings.TrimSpace(string(b))
}
