package host_info

import (
	"agent-wdd/log"
	"bufio"
	"bytes"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
)

// Gather 获取CPU相关的信息
func (cpu *CPU) Gather() {
	log.Info("Gathering INFO => CPU !")

	cpu.getBasicInfo()
	cpu.getVirtualizationInfo()
}

func (cpu *CPU) Save() {
	log.Info("Saving INFO => CPU !")

	ConfigCache.Agent.CPU = *cpu
	SaveConfig()
}

func (cpu *CPU) getBasicInfo() {
	switch runtime.GOOS {
	case "linux":
		cpu.getLinuxCPUInfo()
	case "windows":
		cpu.getWindowsCPUInfo()
	case "darwin":
		cpu.getDarwinCPUInfo()
	default:
		// 其他平台处理
	}
}

func (cpu *CPU) getLinuxCPUInfo() {
	data, err := os.ReadFile("/proc/cpuinfo")
	if err != nil {
		return
	}

	contents := string(data)
	cpu.Cores = strings.Count(contents, "processor\t:")

	// 创建带缓冲的扫描器
	scanner := bufio.NewScanner(bytes.NewReader(data))
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "model name") {
			cpu.Brand = strings.TrimSpace(strings.SplitN(line, ":", 2)[1])
		}
		if strings.Contains(line, "cpu MHz") {
			cpu.Mhz = strings.TrimSpace(strings.Split(line, ":")[1])
		}
	}

	cpu.Arch = runtime.GOARCH
}

func (cpu *CPU) getWindowsCPUInfo() {
	cmd := exec.Command("wmic", "cpu", "get", "Name,NumberOfCores,CurrentClockSpeed", "/VALUE")
	output, err := cmd.Output()
	if err != nil {
		return
	}

	info := string(output)
	lines := strings.Split(info, "\n")
	for _, line := range lines {
		if strings.HasPrefix(line, "Name=") {
			cpu.Brand = strings.TrimSpace(strings.SplitN(line, "=", 2)[1])
		}
		if strings.HasPrefix(line, "NumberOfCores=") {
			cores, _ := strconv.Atoi(strings.SplitN(line, "=", 2)[1])
			cpu.Cores = cores
		}
		if strings.HasPrefix(line, "CurrentClockSpeed=") {
			cpu.Mhz = strings.SplitN(line, "=", 2)[1]
		}
	}

	// 架构处理
	switch runtime.GOARCH {
	case "amd64":
		cpu.Arch = "x86_64"
	default:
		cpu.Arch = runtime.GOARCH
	}
}

func (cpu *CPU) getVirtualizationInfo() {
	switch runtime.GOOS {
	case "linux":
		cpu.getLinuxVirtualization()
	case "windows":
		cpu.getWindowsVirtualization()
	}
}

func (cpu *CPU) getLinuxVirtualization() {
	// 检查CPU虚拟化支持
	data, err := ioutil.ReadFile("/proc/cpuinfo")
	if err == nil {
		if strings.Contains(string(data), "vmx") || strings.Contains(string(data), "svm") {
			cpu.Virt = "supported"
		}
	}

	// 检测是否在虚拟机中
	if _, err := os.Stat("/sys/hypervisor/uid"); !os.IsNotExist(err) {
		cpu.Virt = "virtualized"
		if data, err := ioutil.ReadFile("/sys/hypervisor/type"); err == nil {
			cpu.Hypervisor = strings.TrimSpace(string(data))
		}
		return
	}

	// 使用systemd-detect-virt
	cmd := exec.Command("systemd-detect-virt")
	if output, err := cmd.Output(); err == nil {
		result := strings.TrimSpace(string(output))
		if result != "none" {
			cpu.Virt = "virtualized"
			cpu.Hypervisor = result
		}
	}
}

func (cpu *CPU) getWindowsVirtualization() {
	cmd := exec.Command("wmic", "computersystem", "get", "model", "/VALUE")
	output, err := cmd.Output()
	if err != nil {
		return
	}

	model := strings.ToLower(string(output))
	switch {
	case strings.Contains(model, "virtualbox"):
		cpu.Hypervisor = "VirtualBox"
	case strings.Contains(model, "vmware"):
		cpu.Hypervisor = "VMware"
	case strings.Contains(model, "kvm"):
		cpu.Hypervisor = "KVM"
	case strings.Contains(model, "hyper-v"):
		cpu.Hypervisor = "Hyper-V"
	case strings.Contains(model, "xen"):
		cpu.Hypervisor = "Xen"
	}

	if cpu.Hypervisor != "" {
		cpu.Virt = "virtualized"
	}
}

func (cpu *CPU) getDarwinCPUInfo() {
	// macOS实现
	cmd := exec.Command("sysctl", "-n", "machdep.cpu.brand_string")
	if output, err := cmd.Output(); err == nil {
		cpu.Brand = strings.TrimSpace(string(output))
	}

	cmd = exec.Command("sysctl", "-n", "hw.ncpu")
	if output, err := cmd.Output(); err == nil {
		if cores, err := strconv.Atoi(strings.TrimSpace(string(output))); err == nil {
			cpu.Cores = cores
		}
	}

	cpu.Arch = runtime.GOARCH
}
