//go:build windows

package stats

import (
	"os"
	"runtime"
	"sync"
	"syscall"
	"unsafe"
)

type memoryStatusEx struct {
	Length               uint32
	MemoryLoad           uint32
	TotalPhys            uint64
	AvailPhys            uint64
	TotalPageFile        uint64
	AvailPageFile        uint64
	TotalVirtual         uint64
	AvailVirtual         uint64
	AvailExtendedVirtual uint64
}

var (
	kernel32                 = syscall.NewLazyDLL("kernel32.dll")
	procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx")
)

type Reporter struct {
	mu sync.Mutex

	lastIdle   uint64
	lastKernel uint64
	lastUser   uint64
	hasSample  bool
}

func NewReporter() *Reporter {
	return &Reporter{}
}

func (r *Reporter) SystemInfo() (hostname string, cpuCores int, memoryGB int) {
	hostname, _ = os.Hostname()
	cpuCores = runtime.NumCPU()
	total, _ := r.memoryStatus()
	memoryGB = int(total / (1024 * 1024 * 1024))
	if memoryGB < 1 {
		memoryGB = 1
	}
	return hostname, cpuCores, memoryGB
}

func (r *Reporter) Usage() (cpuPct float64, memPct float64) {
	total, avail := r.memoryStatus()
	if total > 0 {
		memPct = float64(total-avail) / float64(total) * 100
	}
	cpuPct = 0
	return cpuPct, memPct
}

func (r *Reporter) FreeMemoryMB() uint64 {
	_, avail := r.memoryStatus()
	return avail / (1024 * 1024)
}

func (r *Reporter) TotalMemoryMB() uint64 {
	total, _ := r.memoryStatus()
	return total / (1024 * 1024)
}

func (r *Reporter) memoryStatus() (total, avail uint64) {
	var stat memoryStatusEx
	stat.Length = uint32(unsafe.Sizeof(stat))
	ret, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&stat)))
	if ret == 0 {
		return 0, 0
	}
	return stat.TotalPhys, stat.AvailPhys
}
