package collector

import (
	"os/exec"
	"path/filepath"
	"strings"
)

type ServiceInfo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Status      string `json:"status"`
}

func CollectServices() []ServiceInfo {
	// Versuche zuerst pluginctl -s (OPNsense-spezifisch)
	services := tryPluginctl()
	if len(services) > 0 {
		return services
	}

	// Fallback: service -e listet aktivierte Services
	return tryServiceList()
}

// FreeBSD boot/init scripts that run once and are not real services
var ignoredServices = map[string]bool{
	"bgfsck": true, "cleanvar": true, "cleartmp": true, "devmatch": true,
	"dmesg": true, "gptboot": true, "hostid": true, "hostid_save": true,
	"kldxref": true, "mixer": true, "motd": true, "netif": true,
	"newsyslog": true, "os-release": true, "rctl": true, "resolv": true,
	"savecore": true, "utx": true, "var_run": true, "virecover": true,
	"adjkerntz": true, "automount": true, "automountd": true, "autounmountd": true,
	"cron": true, "devd": true, "dhclient": true, "fsck": true,
	"growfs": true, "iovctl": true, "ip6addrctl": true, "ipsec": true,
	"kld": true, "ldconfig": true, "linux": true, "local": true,
	"localpkg": true, "lockd": true, "mdconfig": true, "mdconfig2": true,
	"mountcritlocal": true, "mountcritremote": true, "mountlate": true,
	"msgs": true, "nsswitch": true, "ntpdate": true, "pf": true,
	"pflog": true, "powerd": true, "random": true, "root": true,
	"routing": true, "securelevel": true, "serial": true, "statd": true,
	"swap": true, "swaplate": true, "syscons": true, "sysctl": true,
	"tmp": true, "ugidfw": true, "zfs": true, "zvol": true,
}

func tryPluginctl() []ServiceInfo {
	out, err := exec.Command("/usr/local/sbin/pluginctl", "-s").Output()
	if err != nil {
		return nil
	}

	var services []ServiceInfo
	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		name := strings.TrimSpace(line)
		if name == "" || ignoredServices[name] {
			continue
		}

		// pluginctl -s gibt nur Service-Namen, Status einzeln pruefen
		status := "stopped"
		statusOut, err := exec.Command("service", name, "status").CombinedOutput()
		if err == nil && strings.Contains(string(statusOut), "is running") {
			status = "running"
		}

		// Beschreibung aus rc.d Script extrahieren (# PROVIDE: name)
		desc := ""
		descOut, _ := exec.Command("grep", "-h", "PROVIDE:", "/etc/rc.d/"+name, "/usr/local/etc/rc.d/"+name).Output()
		if len(descOut) > 0 {
			parts := strings.SplitN(string(descOut), "PROVIDE:", 2)
			if len(parts) == 2 {
				desc = strings.TrimSpace(parts[1])
			}
		}

		services = append(services, ServiceInfo{
			Name:        name,
			Description: desc,
			Status:      status,
		})
	}

	return services
}

func tryServiceList() []ServiceInfo {
	out, err := exec.Command("service", "-e").Output()
	if err != nil {
		return nil
	}

	var services []ServiceInfo
	for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
		if line == "" {
			continue
		}

		// service -e gibt volle Pfade: /etc/rc.d/sshd, /usr/local/etc/rc.d/openvpn
		name := filepath.Base(strings.TrimSpace(line))

		// Status pruefen
		status := "running" // service -e listet nur laufende Services
		statusOut, err := exec.Command("service", name, "status").Output()
		if err != nil {
			status = "stopped"
		} else if strings.Contains(string(statusOut), "not running") {
			status = "stopped"
		}

		services = append(services, ServiceInfo{
			Name:   name,
			Status: status,
		})
	}

	return services
}
