package fetchself

import (
	"fmt"
	"log"
	"os/exec"
	"strings"

	"git.lxtend.com/lixiangwuxian/qqbot/constants"
	"git.lxtend.com/lixiangwuxian/qqbot/handler"
	"git.lxtend.com/lixiangwuxian/qqbot/model"
)

func init() {
	handler.RegisterHelpInform("!fetch", "获取系统信息", "!fetch")
	handler.RegisterHandler("!fetch", fetchSelf, constants.LEVEL_USER)
}

var fetchCmd = []string{"fastfetch", "neofetch"}

type SystemInfo struct {
	OS         string
	Host       string
	Kernel     string
	Uptime     string
	CPU        string
	Memory     string
	Disk       string
	GPU        string
	Resolution string
	Packages   string
	Shell      string
	DE         string
	Network    string
	Bluetooth  string
	BIOS       string
}

func (i *SystemInfo) String() string {
	var builder strings.Builder
	if i.OS != "" {
		builder.WriteString(fmt.Sprintf("OS: %s\n", i.OS))
	}
	if i.Host != "" {
		builder.WriteString(fmt.Sprintf("Host: %s\n", i.Host))
	}
	if i.Kernel != "" {
		builder.WriteString(fmt.Sprintf("Kernel: %s\n", i.Kernel))
	}
	if i.Uptime != "" {
		builder.WriteString(fmt.Sprintf("Uptime: %s\n", i.Uptime))
	}
	if i.Packages != "" {
		builder.WriteString(fmt.Sprintf("Packages: %s\n", i.Packages))
	}
	if i.Shell != "" {
		builder.WriteString(fmt.Sprintf("Shell: %s\n", i.Shell))
	}
	if i.Resolution != "" {
		builder.WriteString(fmt.Sprintf("Resolution: %s\n", i.Resolution))
	}
	if i.CPU != "" {
		builder.WriteString(fmt.Sprintf("CPU: %s\n", i.CPU))
	}
	if i.GPU != "" {
		builder.WriteString(fmt.Sprintf("GPU: %s\n", i.GPU))
	}
	if i.Memory != "" {
		builder.WriteString(fmt.Sprintf("Memory: %s\n", i.Memory))
	}
	if i.Disk != "" {
		builder.WriteString(fmt.Sprintf("Disk: %s\n", i.Disk))
	}
	if i.Network != "" {
		builder.WriteString(fmt.Sprintf("Network: %s\n", i.Network))
	}
	if i.Bluetooth != "" {
		builder.WriteString(fmt.Sprintf("Bluetooth: %s\n", i.Bluetooth))
	}
	if i.BIOS != "" {
		builder.WriteString(fmt.Sprintf("BIOS: %s\n", i.BIOS))
	}
	if i.DE != "" {
		builder.WriteString(fmt.Sprintf("DE: %s\n", i.DE))
	}
	return builder.String()
}

func fetchSelf(msg model.Message) (reply *model.Reply) {
	//检测是否存在fetchCmd中的命令
	for _, cmd := range fetchCmd {
		if _, err := exec.LookPath(cmd); err == nil {
			info, err := parseSystemInfo(cmd)
			if err != nil {
				log.Println("parseSystemInfo failed", err)
				return
			}
			reply = &model.Reply{}
			reply.FromMsg = msg
			reply.ReplyMsg = info.String()
			return
		}
	}
	return
}

func parseSystemInfo(cmd string) (SystemInfo, error) {
	switch cmd {
	case "fastfetch":
		fetcher := &fastdfetchParser{}
		return fetcher.Parse(cmd)
	case "neofetch":
		fetcher := &neofetchParser{}
		return fetcher.Parse(cmd)
	}
	return SystemInfo{}, fmt.Errorf("unsupported command: %s", cmd)
}

type Parser interface {
	Parse(cmd string) (SystemInfo, error)
}

type fastdfetchParser struct{}

func (p *fastdfetchParser) Parse(cmd string) (SystemInfo, error) {
	output, err := exec.Command(cmd).Output()
	if err != nil {
		return SystemInfo{}, err
	}
	lines := strings.Split(string(output), "\n")
	info := SystemInfo{}
	for _, line := range lines {
		if strings.Contains(line, "OS:") {
			info.OS = strings.TrimSpace(strings.Split(line, "OS:")[1])
		}
		if strings.Contains(line, "Host:") {
			info.Host = strings.TrimSpace(strings.Split(line, "Host:")[1])
		}
		if strings.Contains(line, "Kernel:") {
			info.Kernel = strings.TrimSpace(strings.Split(line, "Kernel:")[1])
		}
		if strings.Contains(line, "Uptime:") {
			info.Uptime = strings.TrimSpace(strings.Split(line, "Uptime:")[1])
		}
		if strings.Contains(line, "Packages:") {
			info.Packages = strings.TrimSpace(strings.Split(line, "Packages:")[1])
		}
		if strings.Contains(line, "Shell:") {
			info.Shell = strings.TrimSpace(strings.Split(line, "Shell:")[1])
		}
		if strings.Contains(line, "Display (LGD041C):") {
			info.Resolution = strings.TrimSpace(strings.Split(line, "Display (LGD041C):")[1])
		}
		if strings.Contains(line, "CPU:") {
			info.CPU = strings.TrimSpace(strings.Split(line, "CPU:")[1])
		}
		if strings.Contains(line, "GPU:") {
			info.GPU = strings.TrimSpace(strings.Split(line, "GPU:")[1])
		}
		if strings.Contains(line, "Memory:") {
			info.Memory = strings.TrimSpace(strings.Split(line, "Memory:")[1])
		}
		if strings.Contains(line, "Disk (/):") {
			info.Disk = strings.TrimSpace(strings.Split(line, "Disk (/):")[1])
		}
		if strings.Contains(line, "Local IP") {
			info.Network = strings.TrimSpace(strings.Split(line, "Local IP")[1])
		}
	}
	return info, nil
}

type neofetchParser struct{}

func (p *neofetchParser) Parse(cmd string) (SystemInfo, error) {
	output, err := exec.Command(cmd, "--color_blocks", "off").Output()
	if err != nil {
		return SystemInfo{}, err
	}
	lines := strings.Split(string(output), "\n")
	info := SystemInfo{}
	for _, line := range lines {
		if strings.Contains(line, "OS:") {
			info.OS = strings.TrimSpace(strings.Split(line, "OS:")[1])
		}
		if strings.Contains(line, "Host:") {
			info.Host = strings.TrimSpace(strings.Split(line, "Host:")[1])
		}
		if strings.Contains(line, "Kernel:") {
			info.Kernel = strings.TrimSpace(strings.Split(line, "Kernel:")[1])
		}
		if strings.Contains(line, "Uptime:") {
			info.Uptime = strings.TrimSpace(strings.Split(line, "Uptime:")[1])
		}
		if strings.Contains(line, "Packages:") {
			info.Packages = strings.TrimSpace(strings.Split(line, "Packages:")[1])
		}
		if strings.Contains(line, "Shell:") {
			info.Shell = strings.TrimSpace(strings.Split(line, "Shell:")[1])
		}
		if strings.Contains(line, "Resolution:") {
			info.Resolution = strings.TrimSpace(strings.Split(line, "Resolution:")[1])
		}
		if strings.Contains(line, "CPU:") {
			info.CPU = strings.TrimSpace(strings.Split(line, "CPU:")[1])
		}
		if strings.Contains(line, "GPU:") {
			info.GPU = strings.TrimSpace(strings.Split(line, "GPU:")[1])
		}
		if strings.Contains(line, "Memory:") {
			info.Memory = strings.TrimSpace(strings.Split(line, "Memory:")[1])
		}
		if strings.Contains(line, "Network:") {
			info.Network = strings.TrimSpace(strings.Split(line, "Network:")[1])
		}
		if strings.Contains(line, "Bluetooth:") {
			info.Bluetooth = strings.TrimSpace(strings.Split(line, "Bluetooth:")[1])
		}
		if strings.Contains(line, "BIOS:") {
			info.BIOS = strings.TrimSpace(strings.Split(line, "BIOS:")[1])
		}
	}
	return info, nil
}
