package client

import (
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"crypto-miner-agent/deploy"
)

// ResourcePressure is a mining-specific runtime snapshot sent every heartbeat.
// It lets the C2 flag nodes that are thermally or disk-starved BEFORE hashrate
// drops — key for the "is this box safe to mine on?" question.
type ResourcePressure struct {
	// CPU frequency (throttle detection)
	CPUFreqMHz  *int  `json:"cpu_freq_mhz,omitempty"`
	CPUMaxMHz   *int  `json:"cpu_max_mhz,omitempty"`
	CPUThrottle *bool `json:"cpu_throttle,omitempty"` // true when cur < 80% of max

	// CPU thermal
	CPUTempC *int `json:"cpu_temp_c,omitempty"`

	// Disk (drive hosting the miner binary)
	DiskFreeGB  *float64 `json:"disk_free_gb,omitempty"`
	DiskTotalGB *float64 `json:"disk_total_gb,omitempty"`
	DiskFreePct *int     `json:"disk_free_pct,omitempty"`

	// GPU (NVIDIA via nvidia-smi — optional)
	GPUTempC    *int `json:"gpu_temp_c,omitempty"`
	GPUUsagePct *int `json:"gpu_usage_pct,omitempty"`
}

// DiskPressure returns true when less than 10 % of disk is free.
func (r *ResourcePressure) DiskPressure() bool {
	return r != nil && r.DiskFreePct != nil && *r.DiskFreePct < 10
}

// ThermalPressure returns true when CPU > 85 °C or GPU > 82 °C.
func (r *ResourcePressure) ThermalPressure() bool {
	if r == nil {
		return false
	}
	if r.CPUTempC != nil && *r.CPUTempC > 85 {
		return true
	}
	if r.GPUTempC != nil && *r.GPUTempC > 82 {
		return true
	}
	return false
}

// Throttled returns true when the CPU is running below 80 % of its rated speed.
func (r *ResourcePressure) Throttled() bool {
	return r != nil && r.CPUThrottle != nil && *r.CPUThrottle
}

// probeGPU queries nvidia-smi for temperature and utilisation.
// Returns (nil, nil) when no NVIDIA GPU is present or nvidia-smi is absent.
func probeGPU() (tempC, usagePct *int) {
	var out []byte
	var err error
	if runtime.GOOS == "windows" {
		out, err = deploy.HiddenOutput(
			"nvidia-smi",
			"--query-gpu=temperature.gpu,utilization.gpu",
			"--format=csv,noheader,nounits",
		)
	} else {
		out, err = exec.Command(
			"nvidia-smi",
			"--query-gpu=temperature.gpu,utilization.gpu",
			"--format=csv,noheader,nounits",
		).Output()
	}
	if err != nil {
		return nil, nil
	}
	line := strings.TrimSpace(string(out))
	// First GPU only; multi-GPU rigs can extend later.
	parts := strings.SplitN(line, ",", 2)
	if len(parts) >= 1 {
		if n, e := strconv.Atoi(strings.TrimSpace(parts[0])); e == nil {
			tempC = &n
		}
	}
	if len(parts) >= 2 {
		clean := strings.TrimSuffix(strings.TrimSpace(parts[1]), " %")
		if n, e := strconv.Atoi(strings.TrimSpace(clean)); e == nil {
			usagePct = &n
		}
	}
	return
}
