package main

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

const (
	Reset      = "\033[0m"
	GreenBold  = "\033[1;32m"
	BlueBright = "\033[94m"
)

func getDist() string {
	f, _ := os.Open("/etc/os-release")
	defer func(f *os.File) {
		err := f.Close()
		if err != nil {
			fmt.Println("Error closing file:", err)
		}
	}(f)
	s := bufio.NewScanner(f)
	var dist string
	for s.Scan() {
		t := s.Text()
		if strings.HasPrefix(t, "PRETTY_NAME") {
			distro := strings.TrimPrefix(t, "PRETTY_NAME=")
			dist = strings.Trim(distro, "\"")
			break
		}
	}
	dist = strings.TrimSpace(dist)
	return dist
}

func getRam() string {
	f, err := os.Open("/proc/meminfo")
	if err != nil {
		return "error"
	}
	defer f.Close()

	var total, available int
	s := bufio.NewScanner(f)
	for s.Scan() {
		line := s.Text()
		if strings.HasPrefix(line, "MemTotal:") {
			fmt.Sscanf(line, "MemTotal: %d kB", &total)
		}
		if strings.HasPrefix(line, "MemAvailable:") {
			fmt.Sscanf(line, "MemAvailable: %d kB", &available)
		}
	}
	totalMB := total / 1024
	availableMB := available / 1024
	usedMB := totalMB - availableMB

	ram := fmt.Sprintf("%d / %d MiB (%d MiB available)", usedMB, totalMB, availableMB)
	ram = strings.TrimSpace(ram)
	return ram

}

func getCpu() string {
	f, err := os.Open("/proc/cpuinfo")
	if err != nil {
		return "error"
	}
	defer f.Close()

	var cpu string
	s := bufio.NewScanner(f)
	for s.Scan() {
		line := s.Text()
		if strings.HasPrefix(line, "model name") {
			parts := strings.SplitN(line, ":", 2)
			if len(parts) > 1 {
				cpu := strings.TrimSpace(parts[1])
				return cpu
			}
		}
	}

	cpu = fmt.Sprintf(cpu)
	cpu = strings.TrimSpace(cpu)
	return cpu
}

func getGpu() string {
	out, err := exec.Command("sh", "-c", "lspci | grep -E 'VGA|3D'").Output()
	if err != nil {
		return "Unknown GPU"
	}
	line := string(out)
	parts := strings.Split(line, ": ")
	if len(parts) > 1 {
		return cleanGpuString(parts[1])
	}
	return "GPU not found"
}

func cleanGpuString(raw string) string {
	re := regexp.MustCompile(`\(.*\)`)
	res := re.ReplaceAllString(raw, "")
	res = strings.ReplaceAll(res, "Corporation", "")
	res = strings.ReplaceAll(res, "[", "")
	res = strings.ReplaceAll(res, "]", "")
	return strings.Join(strings.Fields(res), " ")
}

func getKernel() string {
	out, err := exec.Command("sh", "-c", "uname -r").Output()
	if err != nil {
		return "Error getting kernel, how did we get there?"
	}
	return strings.TrimSpace(string(out))
}

func getHostname() string {
	hostname, err := exec.Command("sh", "-c", "uname -n").Output()
	if err != nil {
		return "Error getting hostname, awful"
	}
	username, errUser := exec.Command("sh", "-c", "whoami").Output()
	if errUser != nil {
		return "Error getting username, nobody here but us chickens!"
	}
	fullHostname := fmt.Sprintf("%s@%s", strings.TrimSpace(string(username)), strings.TrimSpace(string(hostname)))
	return fullHostname
}

func getPkgs() string {
	var pkgs string
	if strings.HasPrefix(getDist(), "Arch") {
		out, _ := exec.Command("sh", "-c", "pacman -Qq | wc -l").Output()
		pkgs = strings.TrimSpace(string(out)) + " (pacman)"
		return pkgs
	}
	if strings.HasPrefix(getDist(), "Debian") {
		out, _ := exec.Command("sh", "-c", "dpkg -l | grep ^ii | wc -l").Output()
		pkgs = strings.TrimSpace(string(out)) + " (apt)"
		return pkgs
	}
	if strings.HasPrefix(getDist(), "NixOS") {
		out, _ := exec.Command("sh", "-c", "nix-env -qa --installed | wc -l").Output()
		pkgs = strings.TrimSpace(string(out)) + " (nix)"
		return pkgs
	}
	return "unknown"
}

func getAscii() string {
	var ascii string
	if strings.HasPrefix(getDist(), "Arch") {
		content, err := os.ReadFile("ascii/arch.txt")
		if err != nil {
			return "no ascii, but thats arch btw\n"
		}
		ascii = fmt.Sprintf(string(content))
		return ascii
	}
	if strings.HasPrefix(getDist(), "Debian") {
		content, err := os.ReadFile("ascii/debian.txt")
		if err != nil {
			return "no ascii, but thats necrokall\n"
		}
		ascii = fmt.Sprintf(string(content))
		return ascii
	}
	if strings.HasPrefix(getDist(), "NixOS") {
		content, err := os.ReadFile("ascii/nix.txt")
		if err != nil {
			return "no ascii, but thats NIX POBEDA\n"
		}
		ascii = fmt.Sprintf(string(content))
		return ascii
	}
	return "unknown"
}

func main() {
	type Info struct {
		Label string
		Value string
	}

	stats := []Info{
		{"distro", getDist()},
		{"packages", getPkgs()},
		{"kernel", getKernel()},
		{"hostname", getHostname()},
		{"memory", getRam()},
		{"cpu", getCpu()},
		{"gpu", getGpu()},
	}
	fmt.Print(BlueBright)
	fmt.Printf(getAscii())
	fmt.Print(Reset)
	fmt.Printf("\n")
	fmt.Println("---------------------------")

	for _, s := range stats {
		fmt.Printf("> %s%s%s: %s\n", GreenBold, s.Label, Reset, s.Value)
	}

}
