package server

import (
	"runtime"
	"time"

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

const (
	B  = 1
	KB = 1024 * B
	MB = 1024 * KB
	GB = 1024 * MB
)

// Server 服务器信息
type Server struct {
	Os   Os     `json:"os"`
	Cpu  Cpu    `json:"cpu"`
	Ram  Ram    `json:"ram"`
	Disk []Disk `json:"disk"`
}

// Os 操作系统信息
type Os struct {
	GOOS         string `json:"goos"`
	NumCPU       int    `json:"numCpu"`
	Compiler     string `json:"compiler"`
	GoVersion    string `json:"goVersion"`
	NumGoroutine int    `json:"numGoroutine"`
}

// Cpu CPU信息
type Cpu struct {
	Cpus  []float64 `json:"cpus"`
	Cores int       `json:"cores"`
}

// Ram 内存信息
type Ram struct {
	UsedMB      int `json:"usedMb"`
	TotalMB     int `json:"totalMb"`
	UsedPercent int `json:"usedPercent"`
}

// Disk 磁盘信息
type Disk struct {
	MountPoint  string `json:"mountPoint"`
	UsedMB      int    `json:"usedMb"`
	UsedGB      int    `json:"usedGb"`
	TotalMB     int    `json:"totalMb"`
	TotalGB     int    `json:"totalGb"`
	UsedPercent int    `json:"usedPercent"`
}

// InitOS 获取操作系统信息
func InitOS() Os {
	return Os{
		GOOS:         runtime.GOOS,
		NumCPU:       runtime.NumCPU(),
		Compiler:     runtime.Compiler,
		GoVersion:    runtime.Version(),
		NumGoroutine: runtime.NumGoroutine(),
	}
}

// InitCPU 获取CPU信息
func InitCPU() (Cpu, error) {
	var c Cpu
	cores, err := cpu.Counts(false)
	if err != nil {
		return c, err
	}
	c.Cores = cores

	cpus, err := cpu.Percent(time.Duration(200)*time.Millisecond, true)
	if err != nil {
		return c, err
	}
	c.Cpus = cpus
	return c, nil
}

// InitRAM 获取内存信息
func InitRAM() (Ram, error) {
	var r Ram
	u, err := mem.VirtualMemory()
	if err != nil {
		return r, err
	}
	r.UsedMB = int(u.Used) / MB
	r.TotalMB = int(u.Total) / MB
	r.UsedPercent = int(u.UsedPercent)
	return r, nil
}

// InitDisk 获取磁盘信息
func InitDisk(mountPoints []string) ([]Disk, error) {
	var d []Disk
	for _, mp := range mountPoints {
		u, err := disk.Usage(mp)
		if err != nil {
			return d, err
		}
		d = append(d, Disk{
			MountPoint:  mp,
			UsedMB:      int(u.Used) / MB,
			UsedGB:      int(u.Used) / GB,
			TotalMB:     int(u.Total) / MB,
			TotalGB:     int(u.Total) / GB,
			UsedPercent: int(u.UsedPercent),
		})
	}
	return d, nil
}

// GetServerInfo 获取服务器完整信息
func GetServerInfo(diskMountPoints []string) (*Server, error) {
	var s Server
	var err error

	s.Os = InitOS()

	if s.Cpu, err = InitCPU(); err != nil {
		return &s, err
	}

	if s.Ram, err = InitRAM(); err != nil {
		return &s, err
	}

	if len(diskMountPoints) > 0 {
		if s.Disk, err = InitDisk(diskMountPoints); err != nil {
			return &s, err
		}
	}

	return &s, nil
}
