package main

import (
	"bufio"
	"errors"
	"os"
	"strconv"
	"strings"
	"time"
)

// readCPUUsage 读取CPU整体使用率
func readCPUUsage() (float64, error) {
	idle1, total1, err := readCPUTicks()
	if err != nil {
		return 0, err
	}
	time.Sleep(250 * time.Millisecond)
	idle2, total2, err := readCPUTicks()
	if err != nil {
		return 0, err
	}
	if total2 == total1 {
		return 0, errors.New("cpu totals unchanged")
	}
	idleDelta := float64(idle2 - idle1)
	totalDelta := float64(total2 - total1)
	usage := (1.0 - idleDelta/totalDelta) * 100
	if usage < 0 {
		usage = 0
	}
	return usage, nil
}

// readCPUTicks 读取CPU的idle和total ticks
func readCPUTicks() (idle, total uint64, err error) {
	f, err := os.Open("/proc/stat")
	if err != nil {
		return 0, 0, err
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	if !scanner.Scan() {
		return 0, 0, errors.New("failed to scan /proc/stat")
	}
	fields := strings.Fields(scanner.Text())
	if len(fields) < 5 {
		return 0, 0, errors.New("unexpected /proc/stat format")
	}
	// fields[0] is "cpu"
	var vals []uint64
	for _, f := range fields[1:] {
		v, err := strconv.ParseUint(f, 10, 64)
		if err != nil {
			return 0, 0, err
		}
		vals = append(vals, v)
	}
	for _, v := range vals {
		total += v
	}
	if len(vals) > 3 {
		idle = vals[3] // idle time
		// 注意：不包含 iowait，因为 iowait 不算真正的空闲时间
		// 如果系统有 iowait，它会在 total 中，但不应该算作 idle
	}
	return idle, total, nil
}

// readPerCoreUsage 读取每个CPU核心的使用率
func readPerCoreUsage() []CoreUsage {
	coreUsages := []CoreUsage{}

	// 第一次读取
	cores1 := readPerCoreTicks()
	time.Sleep(100 * time.Millisecond) // 减少到100ms
	// 第二次读取
	cores2 := readPerCoreTicks()

	for i := 0; i < len(cores1) && i < len(cores2); i++ {
		idle1, total1 := cores1[i][0], cores1[i][1]
		idle2, total2 := cores2[i][0], cores2[i][1]

		if total2 == total1 {
			continue
		}

		idleDelta := float64(idle2 - idle1)
		totalDelta := float64(total2 - total1)
		usage := (1.0 - idleDelta/totalDelta) * 100
		if usage < 0 {
			usage = 0
		}

		coreUsages = append(coreUsages, CoreUsage{
			Core:    i,
			Percent: round(usage, 1),
		})
	}

	return coreUsages
}

// readPerCoreTicks 读取每个CPU核心的ticks
func readPerCoreTicks() [][2]uint64 {
	var result [][2]uint64

	f, err := os.Open("/proc/stat")
	if err != nil {
		return result
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		if !strings.HasPrefix(line, "cpu") {
			continue
		}
		if strings.HasPrefix(line, "cpu ") {
			continue // 跳过总的cpu行
		}

		fields := strings.Fields(line)
		if len(fields) < 5 {
			continue
		}

		var vals []uint64
		for _, f := range fields[1:] {
			v, err := strconv.ParseUint(f, 10, 64)
			if err != nil {
				break
			}
			vals = append(vals, v)
		}

		if len(vals) < 5 {
			continue
		}

		var total, idle uint64
		for _, v := range vals {
			total += v
		}
		idle = vals[3] // idle time only, not including iowait

		result = append(result, [2]uint64{idle, total})
	}

	return result
}

// readCPUTemperature 读取CPU温度
func readCPUTemperature() float64 {
	// 尝试从常见位置读取温度
	paths := []string{
		"/sys/class/thermal/thermal_zone0/temp",
		"/sys/class/hwmon/hwmon0/temp1_input",
		"/sys/class/hwmon/hwmon1/temp1_input",
	}
	for _, path := range paths {
		if temp := readTempFromFile(path); temp > 0 {
			return temp
		}
	}
	return 0
}

// readLoadAverages 读取系统负载平均值
func readLoadAverages() []float64 {
	line := readFirstLine("/proc/loadavg")
	fields := strings.Fields(line)
	res := make([]float64, 0, 3)
	for i := 0; i < len(fields) && i < 3; i++ {
		v, err := strconv.ParseFloat(fields[i], 64)
		if err == nil {
			res = append(res, v)
		}
	}
	return res
}
