package service

import (
	"bufio"
	"fmt"
	"os"
	"runtime"
	"strings"
	"time"

	"ems.agt/src/framework/config"
	"ems.agt/src/framework/utils/parse"

	"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"
)

// 实例化服务层 SystemInfoImpl 结构体
var NewSystemInfoImpl = &SystemInfoImpl{}

// SystemInfoImpl 服务器系统相关信息 服务层处理
type SystemInfoImpl struct{}

// ProjectInfo 程序项目信息
func (s *SystemInfoImpl) ProjectInfo() map[string]any {
	// 获取工作目录
	appDir, err := os.Getwd()
	if err != nil {
		appDir = ""
	}
	// 项目依赖
	dependencies := s.dependencies()
	return map[string]any{
		"appDir":       appDir,
		"env":          config.Env(),
		"name":         config.Get("framework.name"),
		"version":      config.Get("framework.version"),
		"dependencies": dependencies,
	}
}

// dependencies 读取mod内项目包依赖
func (s *SystemInfoImpl) dependencies() map[string]string {
	var pkgs = make(map[string]string)

	// 打开 go.mod 文件
	file, err := os.Open("go.mod")
	if err != nil {
		return pkgs
	}
	defer file.Close()

	// 使用 bufio.Scanner 逐行读取文件内容
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		line = strings.TrimSpace(line)

		// 行不为空，不以module\require开头，不带有 // indirect 注释，则解析包名和版本
		prefixLine := strings.HasPrefix(line, "module") || strings.HasPrefix(line, "require") || strings.HasPrefix(line, "go ")
		suffixLine := strings.HasSuffix(line, ")") || strings.HasSuffix(line, "// indirect")
		if line == "" || prefixLine || suffixLine {
			continue
		}

		modInfo := strings.Split(line, " ")
		if len(modInfo) >= 2 {
			moduleName := strings.TrimSpace(modInfo[0])
			version := strings.TrimSpace(modInfo[1])
			pkgs[moduleName] = version
		}
	}

	if err := scanner.Err(); err != nil {
		pkgs["scanner-err"] = err.Error()
	}
	return pkgs
}

// SystemInfo 系统信息
func (s *SystemInfoImpl) SystemInfo() map[string]any {
	info, err := host.Info()
	if err != nil {
		info.Platform = err.Error()
	}
	// 用户目录
	homeDir, err := os.UserHomeDir()
	if err != nil {
		homeDir = ""
	}
	cmd, err := os.Executable()
	if err != nil {
		cmd = ""
	}
	return map[string]any{
		"platform":    info.Platform,
		"go":          runtime.Version(),
		"processId":   os.Getpid(),
		"arch":        info.KernelArch,
		"uname":       runtime.GOARCH,
		"release":     info.OS,
		"hostname":    info.Hostname,
		"homeDir":     homeDir,
		"cmd":         cmd,
		"execCommand": strings.Join(os.Args, " "),
	}
}

// TimeInfo 系统时间信息
func (s *SystemInfoImpl) TimeInfo() map[string]string {
	// 获取当前时间
	current := time.Now().Format("2006-01-02 15:04:05")
	// 获取程序运行时间
	uptime := time.Since(config.RunTime()).String()
	// 获取时区
	timezone := time.Now().Format("-0700 MST")
	// 获取时区名称
	timezoneName := time.Now().Format("MST")

	return map[string]string{
		"current":      current,
		"uptime":       uptime,
		"timezone":     timezone,
		"timezoneName": timezoneName,
	}
}

// MemoryInfo 内存信息
func (s *SystemInfoImpl) MemoryInfo() map[string]any {
	memInfo, err := mem.VirtualMemory()
	if err != nil {
		memInfo.UsedPercent = 0
		memInfo.Available = 0
		memInfo.Total = 0
	}

	var memStats runtime.MemStats
	runtime.ReadMemStats(&memStats)

	return map[string]any{
		"usage":     fmt.Sprintf("%.2f", memInfo.UsedPercent),            // 内存利用率
		"freemem":   parse.Bit(float64(memInfo.Available)),               // 可用内存大小（GB）
		"totalmem":  parse.Bit(float64(memInfo.Total)),                   // 总内存大小（GB）
		"rss":       parse.Bit(float64(memStats.Sys)),                    // 常驻内存大小（RSS）
		"heapTotal": parse.Bit(float64(memStats.HeapSys)),                // 堆总大小
		"heapUsed":  parse.Bit(float64(memStats.HeapAlloc)),              // 堆已使用大小
		"external":  parse.Bit(float64(memStats.Sys - memStats.HeapSys)), // 外部内存大小（非堆）
	}
}

// CPUInfo CPU信息
func (s *SystemInfoImpl) CPUInfo() map[string]any {
	var core int32 = 0
	var speed string = "未知"
	var model string = "未知"
	cpuInfo, err := cpu.Info()
	if err == nil {
		core = cpuInfo[0].Cores
		speed = fmt.Sprintf("%.0fMHz", cpuInfo[0].Mhz)
		model = strings.TrimSpace(cpuInfo[0].ModelName)
	}

	useds := []string{}
	cpuPercent, err := cpu.Percent(0, true)
	if err == nil {
		for _, v := range cpuPercent {
			useds = append(useds, fmt.Sprintf("%.2f", v))
		}
	}

	return map[string]any{
		"model":    model,
		"speed":    speed,
		"core":     core,
		"coreUsed": useds,
	}
}

// NetworkInfo 网络信息
func (s *SystemInfoImpl) NetworkInfo() map[string]string {
	ipAddrs := make(map[string]string)
	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			name := iface.Name
			if name[len(name)-1] == '0' {
				name = name[0 : len(name)-1]
				name = strings.Trim(name, "")
			}
			// ignore localhost
			if name == "lo" {
				continue
			}
			var addrs []string
			for _, v := range iface.Addrs {
				prefix := strings.Split(v.Addr, "/")[0]
				if strings.Contains(prefix, "::") {
					addrs = append(addrs, fmt.Sprintf("IPv6 %s", prefix))
				}
				if strings.Contains(prefix, ".") {
					addrs = append(addrs, fmt.Sprintf("IPv4 %s", prefix))
				}
			}
			ipAddrs[name] = strings.Join(addrs, " / ")
		}
	}
	return ipAddrs
}

// DiskInfo 磁盘信息
func (s *SystemInfoImpl) DiskInfo() []map[string]string {
	disks := make([]map[string]string, 0)

	partitions, err := disk.Partitions(false)
	if err != nil {
		return disks
	}

	for _, partition := range partitions {
		usage, err := disk.Usage(partition.Mountpoint)
		if err != nil {
			continue
		}
		disks = append(disks, map[string]string{
			"size":   parse.Bit(float64(usage.Total)),
			"used":   parse.Bit(float64(usage.Used)),
			"avail":  parse.Bit(float64(usage.Free)),
			"pcent":  fmt.Sprintf("%.1f%%", usage.UsedPercent),
			"target": partition.Device,
		})
	}
	return disks
}
