//go:build darwin
// +build darwin

package sys

import (
	"encoding/binary"
	"fmt"
	"sync"
	"syscall"

	"github.com/shirou/gopsutil/v4/net"
	"golang.org/x/sys/unix"
)

var SIGUSR1 = syscall.SIGUSR1

func GetTCPCount() (int, error) {
	stats, err := net.Connections("tcp")
	if err != nil {
		return 0, err
	}
	return len(stats), nil
}

func GetUDPCount() (int, error) {
	stats, err := net.Connections("udp")
	if err != nil {
		return 0, err
	}
	return len(stats), nil
}

// --- CPU Utilization (macOS native) ---

// sysctl kern.cp_time returns an array of 5 longs: user, nice, sys, idle, intr.
// We compute utilization deltas without cgo.
var (
	cpuMu       sync.Mutex
	lastTotals  [5]uint64
	hasLastCPUT bool
)

func CPUPercentRaw() (float64, error) {
	raw, err := unix.SysctlRaw("kern.cp_time")
	if err != nil {
		return 0, err
	}
	// Expect either 5*8 bytes (uint64) or 5*4 bytes (uint32)
	var out [5]uint64
	switch len(raw) {
	case 5 * 8:
		for i := range 5 {
			out[i] = binary.LittleEndian.Uint64(raw[i*8 : (i+1)*8])
		}
	case 5 * 4:
		for i := range 5 {
			out[i] = uint64(binary.LittleEndian.Uint32(raw[i*4 : (i+1)*4]))
		}
	default:
		return 0, fmt.Errorf("unexpected kern.cp_time size: %d", len(raw))
	}

	// user, nice, sys, idle, intr
	user := out[0]
	nice := out[1]
	sysv := out[2]
	idle := out[3]
	intr := out[4]

	cpuMu.Lock()
	defer cpuMu.Unlock()

	if !hasLastCPUT {
		lastTotals = out
		hasLastCPUT = true
		return 0, nil
	}

	dUser := user - lastTotals[0]
	dNice := nice - lastTotals[1]
	dSys := sysv - lastTotals[2]
	dIdle := idle - lastTotals[3]
	dIntr := intr - lastTotals[4]

	lastTotals = out

	totald := dUser + dNice + dSys + dIdle + dIntr
	if totald == 0 {
		return 0, nil
	}
	busy := totald - dIdle
	pct := float64(busy) / float64(totald) * 100.0
	if pct > 100 {
		pct = 100
	}
	return pct, nil
}
