package collector

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

type CPUInfo struct {
	Model        string
	Cores        int
	Threads      int
	FreqMHz      int
	UsagePercent float64
}

func CollectCPU() CPUInfo {
	cpu := CPUInfo{}
	
	// CPU-Informationen aus /proc/cpuinfo lesen
	if data, err := os.ReadFile("/proc/cpuinfo"); err == nil {
		lines := strings.Split(string(data), "\n")
		cpuCount := 0
		
		for _, line := range lines {
			line = strings.TrimSpace(line)
			if line == "" {
				continue
			}
			
			parts := strings.SplitN(line, ":", 2)
			if len(parts) != 2 {
				continue
			}
			
			key := strings.TrimSpace(parts[0])
			value := strings.TrimSpace(parts[1])
			
			switch key {
			case "model name":
				if cpu.Model == "" { // Nur vom ersten CPU nehmen
					cpu.Model = value
				}
			case "cpu MHz":
				if cpu.FreqMHz == 0 { // Nur vom ersten CPU nehmen
					if freq, err := strconv.ParseFloat(value, 64); err == nil {
						cpu.FreqMHz = int(freq)
					}
				}
			case "processor":
				cpuCount++
			case "cpu cores":
				if cores, err := strconv.Atoi(value); err == nil && cpu.Cores == 0 {
					cpu.Cores = cores
				}
			case "siblings":
				if threads, err := strconv.Atoi(value); err == nil && cpu.Threads == 0 {
					cpu.Threads = threads
				}
			}
		}
		
		// Falls cpu cores und siblings nicht vorhanden, nutze processor count
		if cpu.Cores == 0 {
			cpu.Cores = cpuCount
		}
		if cpu.Threads == 0 {
			cpu.Threads = cpuCount
		}
	}
	
	// CPU-Usage berechnen
	cpu.UsagePercent = calculateCPUUsage()
	
	return cpu
}

// Berechnet die aktuelle CPU-Auslastung über zwei /proc/stat Messungen
func calculateCPUUsage() float64 {
	stat1 := readCPUStat()
	if stat1 == nil {
		return 0.0
	}
	
	time.Sleep(100 * time.Millisecond) // Kurz warten für zweite Messung
	
	stat2 := readCPUStat()
	if stat2 == nil {
		return 0.0
	}
	
	// Delta berechnen
	totalDelta := (stat2.total - stat1.total)
	idleDelta := (stat2.idle - stat1.idle)
	
	if totalDelta <= 0 {
		return 0.0
	}
	
	usage := 100.0 * float64(totalDelta-idleDelta) / float64(totalDelta)
	if usage < 0 {
		usage = 0
	}
	if usage > 100 {
		usage = 100
	}
	
	return usage
}

type cpuStat struct {
	total int64
	idle  int64
}

// Liest CPU-Statistiken aus /proc/stat
func readCPUStat() *cpuStat {
	data, err := os.ReadFile("/proc/stat")
	if err != nil {
		return nil
	}
	
	lines := strings.Split(string(data), "\n")
	if len(lines) == 0 {
		return nil
	}
	
	// Erste Zeile sollte "cpu ..." sein
	firstLine := strings.TrimSpace(lines[0])
	if !strings.HasPrefix(firstLine, "cpu ") {
		return nil
	}
	
	fields := strings.Fields(firstLine)
	if len(fields) < 5 {
		return nil
	}
	
	// cpu user nice system idle iowait irq softirq ...
	var values []int64
	for i := 1; i < len(fields) && i <= 7; i++ { // max 7 Werte lesen
		if val, err := strconv.ParseInt(fields[i], 10, 64); err == nil {
			values = append(values, val)
		}
	}
	
	if len(values) < 4 {
		return nil
	}
	
	// Total = Summe aller Werte
	total := int64(0)
	for _, val := range values {
		total += val
	}
	
	// Idle = idle + iowait (falls iowait verfügbar)
	idle := values[3] // idle
	if len(values) > 4 {
		idle += values[4] // + iowait
	}
	
	return &cpuStat{
		total: total,
		idle:  idle,
	}
}