package workloads

import (
	"context"
	"os/exec"
	"strings"
	"time"
)

const systemdTimeout = 30 * time.Second

// excludedPrefixes drops the platform's own units. A typical host carries 300+
// units and systemd accounts for most of them; listing all of them buries the
// ten anyone cares about.
var excludedPrefixes = []string{"systemd-", "user@", "user-", "session-", "init.scope"}

// collectSystemd enumerates services in two passes, because "running or
// failed" and "enabled but stopped" are different questions — and an enabled
// unit that is not running is exactly the one worth seeing.
func collectSystemd(ctx context.Context) ([]Workload, bool, string) {
	if _, err := exec.LookPath("systemctl"); err != nil {
		return nil, false, ""
	}

	ctx, cancel := context.WithTimeout(ctx, systemdTimeout)
	defer cancel()

	// Column output rather than --output=json: the JSON flag needs systemd
	// 246+, and this fleet includes older stable distributions. The columns
	// have been stable considerably longer than the JSON has existed.
	unitsOut, err := exec.CommandContext(ctx, "systemctl",
		"list-units", "--type=service", "--state=running,failed",
		"--no-legend", "--plain", "--no-pager").Output()
	if err != nil {
		return nil, false, "systemctl list-units failed: " + errText(err)
	}

	seen := map[string]bool{}
	var wls []Workload

	for _, line := range strings.Split(string(unitsOut), "\n") {
		f := strings.Fields(line)
		// UNIT LOAD ACTIVE SUB DESCRIPTION…
		if len(f) < 4 {
			continue
		}
		name := f[0]
		if excluded(name) || seen[name] {
			continue
		}
		seen[name] = true
		wls = append(wls, Workload{
			Kind:  "unit",
			ID:    name,
			Name:  strings.TrimSuffix(name, ".service"),
			State: f[2], // ACTIVE: active | failed | activating | inactive
		})
	}

	filesOut, err := exec.CommandContext(ctx, "systemctl",
		"list-unit-files", "--type=service", "--state=enabled",
		"--no-legend", "--plain", "--no-pager").Output()
	if err == nil {
		for _, line := range strings.Split(string(filesOut), "\n") {
			f := strings.Fields(line)
			// UNIT FILE  STATE  [PRESET]
			if len(f) < 2 {
				continue
			}
			name := f[0]
			if excluded(name) || seen[name] {
				continue
			}
			seen[name] = true
			wls = append(wls, Workload{
				Kind:  "unit",
				ID:    name,
				Name:  strings.TrimSuffix(name, ".service"),
				State: "inactive", // enabled but not currently running
			})
		}
	}

	return wls, true, ""
}

func excluded(name string) bool {
	for _, p := range excludedPrefixes {
		if strings.HasPrefix(name, p) {
			return true
		}
	}
	return false
}
