package service

import (
	"licserver/internal/model"

	"runtime"

	"time"

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

	"github.com/shirou/gopsutil/v3/disk"

	"github.com/shirou/gopsutil/v3/host"

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

	"github.com/shirou/gopsutil/v3/net"

	"github.com/shirou/gopsutil/v3/process"

	"gorm.io/gorm"
)

type MonitorService struct {
	db *gorm.DB

	startTime time.Time
}

func NewMonitorService(db *gorm.DB) *MonitorService {

	return &MonitorService{

		db: db,

		startTime: time.Now(),
	}

}

func (s *MonitorService) GetSystemStatus() (*model.SystemStatus, error) {

	status := &model.SystemStatus{}

	// CPU信息

	if err := s.getCPUInfo(status); err != nil {

		return nil, err

	}

	// 内存信息

	if err := s.getMemoryInfo(status); err != nil {

		return nil, err

	}

	// 磁盘信息

	if err := s.getDiskInfo(status); err != nil {

		return nil, err

	}

	// 网络信息

	if err := s.getNetworkInfo(status); err != nil {

		return nil, err

	}

	// 进程信息

	if err := s.getProcessInfo(status); err != nil {

		return nil, err

	}

	// 主机信息

	if err := s.getHostInfo(status); err != nil {

		return nil, err

	}

	// 系统信息

	s.getSystemInfo(status)

	return status, nil

}

func (s *MonitorService) getCPUInfo(status *model.SystemStatus) error {

	cpuPercent, err := cpu.Percent(time.Second, false)

	if err != nil {

		return err

	}

	// Windows 系统不支持 LoadAvg，设置为默认值

	status.CPU.LoadAvg = []float64{0, 0, 0}

	cpuInfo, err := cpu.Info()

	if err != nil {

		return err

	}

	status.CPU.Usage = cpuPercent[0]

	status.CPU.CoreCount = runtime.NumCPU()

	if len(cpuInfo) > 0 {

		status.CPU.ModelName = cpuInfo[0].ModelName

		status.CPU.MHz = cpuInfo[0].Mhz

	}

	return nil

}

func (s *MonitorService) getMemoryInfo(status *model.SystemStatus) error {

	memInfo, err := mem.VirtualMemory()

	if err != nil {

		return err

	}

	swapInfo, err := mem.SwapMemory()

	if err != nil {

		return err

	}

	status.Memory.Total = memInfo.Total

	status.Memory.Used = memInfo.Used

	status.Memory.Free = memInfo.Free

	status.Memory.UsageRate = memInfo.UsedPercent

	status.Memory.SwapTotal = swapInfo.Total

	status.Memory.SwapUsed = swapInfo.Used

	status.Memory.SwapFree = swapInfo.Free

	status.Memory.SwapUsageRate = swapInfo.UsedPercent

	return nil

}

func (s *MonitorService) getDiskInfo(status *model.SystemStatus) error {

	partitions, err := disk.Partitions(true)

	if err != nil {

		return err

	}

	status.Disk.Partitions = make([]model.DiskPartition, 0)

	for _, partition := range partitions {

		usage, err := disk.Usage(partition.Mountpoint)

		if err != nil {

			continue

		}

		status.Disk.Partitions = append(status.Disk.Partitions, model.DiskPartition{
			Device:     partition.Device,
			Mountpoint: partition.Mountpoint,
			Fstype:     partition.Fstype,
			Total:      usage.Total,
			Used:       usage.Used,
			Free:       usage.Free,
			UsageRate:  usage.UsedPercent,
		})

	}

	return nil

}

func (s *MonitorService) getNetworkInfo(status *model.SystemStatus) error {

	interfaces, err := net.Interfaces()

	if err != nil {

		return err

	}

	ioCounters, err := net.IOCounters(true)

	if err != nil {

		return err

	}

	status.Network.Interfaces = make([]model.NetworkInterface, 0)

	for _, iface := range interfaces {

		var counter net.IOCountersStat

		for _, io := range ioCounters {

			if io.Name == iface.Name {
				counter = io
				break
			}
		}

		// 获取接口的地址列表

		addrs := make([]string, 0)

		for _, addr := range iface.Addrs {
			addrs = append(addrs, addr.String())
		}

		status.Network.Interfaces = append(status.Network.Interfaces, model.NetworkInterface{

			Name: iface.Name,

			BytesSent: counter.BytesSent,

			BytesRecv: counter.BytesRecv,

			PacketsSent: counter.PacketsSent,

			PacketsRecv: counter.PacketsRecv,

			Addrs: addrs,
		})

	}

	return nil

}

func (s *MonitorService) getProcessInfo(status *model.SystemStatus) error {

	processes, err := process.Processes()

	if err != nil {

		return err

	}

	status.Process.Total = len(processes)

	status.Process.List = make([]model.ProcessInfo, 0)

	for i := 0; i < 10 && i < len(processes); i++ {

		p := processes[i]

		name, _ := p.Name()

		cpu, _ := p.CPUPercent()

		mem, _ := p.MemoryPercent()

		created, _ := p.CreateTime()

		status.Process.List = append(status.Process.List, model.ProcessInfo{

			PID: int(p.Pid),

			Name: name,

			CPU: cpu,

			Memory: float64(mem),

			Created: created,
		})

	}

	return nil

}

func (s *MonitorService) getHostInfo(status *model.SystemStatus) error {

	info, err := host.Info()

	if err != nil {

		return err

	}

	status.Host.Hostname = info.Hostname

	status.Host.OS = info.OS

	status.Host.Platform = info.Platform

	status.Host.PlatformVersion = info.PlatformVersion

	status.Host.KernelVersion = info.KernelVersion

	status.Host.BootTime = time.Unix(int64(info.BootTime), 0)

	return nil

}

func (s *MonitorService) getSystemInfo(status *model.SystemStatus) {

	status.System.Uptime = time.Since(s.startTime)

	status.System.CurrentTime = time.Now()

	var activeUsers int64

	s.db.Model(&model.User{}).Count(&activeUsers)

	status.System.ActiveUsers = int(activeUsers)

	var totalDevices int64

	s.db.Model(&model.Device{}).Count(&totalDevices)

	status.System.TotalDevices = int(totalDevices)

}
