package collector

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

type NetworkInterface struct {
	Name    string `json:"name"`
	Role    string `json:"role"`
	IP      string `json:"ip"`
	MAC     string `json:"mac"`
	Status  string `json:"status"`
	RxBytes int64  `json:"rx_bytes"`
	TxBytes int64  `json:"tx_bytes"`
}

func CollectNetwork() []NetworkInterface {
	var interfaces []NetworkInterface
	
	// Interface-Statistiken aus /proc/net/dev lesen
	stats := readNetDevStats()
	
	// Interface-Informationen aus /sys/class/net/* sammeln
	entries, err := os.ReadDir("/sys/class/net")
	if err != nil {
		return interfaces
	}
	
	for _, entry := range entries {
		if !entry.IsDir() {
			continue
		}
		
		ifName := entry.Name()
		
		// Überspringe loopback
		if ifName == "lo" {
			continue
		}
		
		iface := NetworkInterface{
			Name: ifName,
			Role: determineInterfaceRole(ifName),
		}
		
		// Status aus operstate lesen
		if data, err := os.ReadFile("/sys/class/net/" + ifName + "/operstate"); err == nil {
			state := strings.TrimSpace(string(data))
			if state == "up" {
				iface.Status = "up"
			} else {
				iface.Status = "down"
			}
		}
		
		// MAC-Adresse lesen
		if data, err := os.ReadFile("/sys/class/net/" + ifName + "/address"); err == nil {
			iface.MAC = strings.TrimSpace(string(data))
		}
		
		// Statistiken hinzufügen
		if stat, exists := stats[ifName]; exists {
			iface.RxBytes = stat.rxBytes
			iface.TxBytes = stat.txBytes
		}
		
		// IP-Adresse über ip addr bestimmen
		iface.IP = getInterfaceIP(ifName)
		
		interfaces = append(interfaces, iface)
	}
	
	return interfaces
}

// Bestimmt die Rolle eines Interfaces basierend auf dem Namen
func determineInterfaceRole(ifName string) string {
	switch {
	case strings.HasPrefix(ifName, "eth"):
		return "lan"
	case strings.HasPrefix(ifName, "ens"):
		return "lan"
	case strings.HasPrefix(ifName, "enp"):
		return "lan"
	case strings.HasPrefix(ifName, "wlan"):
		return "wan"
	case strings.HasPrefix(ifName, "wlp"):
		return "wan"
	case strings.HasPrefix(ifName, "ppp"):
		return "wan"
	case strings.HasPrefix(ifName, "tun"):
		return "vpn"
	case strings.HasPrefix(ifName, "tap"):
		return "vpn"
	case strings.HasPrefix(ifName, "br"):
		return "bridge"
	case strings.HasPrefix(ifName, "docker"):
		return "virtual"
	case strings.HasPrefix(ifName, "veth"):
		return "virtual"
	case strings.HasPrefix(ifName, "virbr"):
		return "virtual"
	default:
		return "other"
	}
}

// Liest die erste IPv4-Adresse eines Interfaces
func getInterfaceIP(ifName string) string {
	output, err := exec.Command("/usr/sbin/ip", "-4", "addr", "show", ifName).CombinedOutput()
	if err != nil {
		return ""
	}
	
	lines := strings.Split(string(output), "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "inet ") {
			fields := strings.Fields(line)
			if len(fields) >= 2 {
				// inet 192.168.1.100/24 ... -> 192.168.1.100
				ipCidr := fields[1]
				if parts := strings.SplitN(ipCidr, "/", 2); len(parts) > 0 {
					return parts[0]
				}
			}
		}
	}
	
	return ""
}

// Network-Statistiken
type netDevStat struct {
	rxBytes int64
	txBytes int64
}

// Liest Interface-Statistiken aus /proc/net/dev
func readNetDevStats() map[string]netDevStat {
	stats := make(map[string]netDevStat)
	
	data, err := os.ReadFile("/proc/net/dev")
	if err != nil {
		return stats
	}
	
	lines := strings.Split(string(data), "\n")
	if len(lines) < 3 {
		return stats
	}
	
	// Ersten 2 Zeilen sind Header
	for _, line := range lines[2:] {
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		
		// Interface: rx_bytes rx_packets ... tx_bytes tx_packets ...
		parts := strings.SplitN(line, ":", 2)
		if len(parts) != 2 {
			continue
		}
		
		ifName := strings.TrimSpace(parts[0])
		values := strings.Fields(strings.TrimSpace(parts[1]))
		
		if len(values) >= 9 {
			// rx_bytes ist das erste Feld, tx_bytes das 9te Feld (0-basiert: Index 8)
			rxBytes, _ := strconv.ParseInt(values[0], 10, 64)
			txBytes, _ := strconv.ParseInt(values[8], 10, 64)
			
			stats[ifName] = netDevStat{
				rxBytes: rxBytes,
				txBytes: txBytes,
			}
		}
	}
	
	return stats
}