// cmd/sysusage/main.go
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/shirou/gopsutil/v3/mem"
)

type Result struct {
	CPUPercent float64 `json:"cpu_percent"`
	RAMPercent float64 `json:"ram_percent"`
}

func sampleCPU(interval time.Duration, samples int) (float64, error) {
	if samples <= 0 {
		samples = 1
	}
	var sum float64
	for i := 0; i < samples; i++ {
		// cpu.Percent blockiert für "interval" und liefert die Auslastung in diesem Zeitfenster
		values, err := cpu.Percent(interval, false)
		if err != nil {
			return 0, err
		}
		if len(values) == 0 {
			return 0, fmt.Errorf("no cpu values returned")
		}
		sum += values[0]
	}
	return sum / float64(samples), nil
}

func readRAM() (float64, error) {
	vm, err := mem.VirtualMemory()
	if err != nil {
		return 0, err
	}
	return vm.UsedPercent, nil
}

func main() {
	var (
		intervalStr string
		samples     int
		jsonOut     bool
		watch       bool
	)

	flag.StringVar(&intervalStr, "interval", "1s", "Messintervall pro Stichprobe (z.B. 200ms, 1s, 2s)")
	flag.IntVar(&samples, "samples", 1, "Anzahl der Stichproben (über das Intervall gemittelt)")
	flag.BoolVar(&jsonOut, "json", false, "Ausgabe als JSON")
	flag.BoolVar(&watch, "watch", false, "Kontinuierlich messen, bis Strg+C")
	flag.Parse()

	interval, err := time.ParseDuration(intervalStr)
	if err != nil || interval <= 0 {
		log.Fatalf("ungültiges -interval: %v", intervalStr)
	}

	printOnce := func() error {
		cpuPct, err := sampleCPU(interval, samples)
		if err != nil {
			return fmt.Errorf("CPU-Messung fehlgeschlagen: %w", err)
		}
		ramPct, err := readRAM()
		if err != nil {
			return fmt.Errorf("RAM-Messung fehlgeschlagen: %w", err)
		}

		if jsonOut {
			out := Result{CPUPercent: cpuPct, RAMPercent: ramPct}
			enc := json.NewEncoder(stdoutNoHTMLEscape{})
			enc.SetIndent("", "  ")
			return enc.Encode(out)
		}

		fmt.Printf("CPU: %.1f%% | RAM: %.1f%%\n", cpuPct, ramPct)
		return nil
	}

	if watch {
		for {
			if err := printOnce(); err != nil {
				log.Fatal(err)
			}
			// Bei watch: zwischen den Zeilen kurz pausieren, damit die Ausgabe lesbar bleibt.
			time.Sleep(250 * time.Millisecond)
		}
	} else {
		if err := printOnce(); err != nil {
			log.Fatal(err)
		}
	}
}

// stdoutNoHTMLEscape verhindert das HTML-Escaping des Standard-Encoders (nur Kosmetik für JSON)
type stdoutNoHTMLEscape struct{}

func (stdoutNoHTMLEscape) Write(p []byte) (int, error) { return fmt.Print(string(p)) }
func (stdoutNoHTMLEscape) Encode(v any) error {
	enc := json.NewEncoder(stdoutNoHTMLEscape{})
	enc.SetEscapeHTML(false)
	return enc.Encode(v)
}

