package workloads

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"runtime"
	"sort"
	"strconv"
	"strings"
)

// Result is one collection pass.
type Result struct {
	Workloads    []Workload
	DockerOK     bool
	DockerError  string
	SystemdOK    bool
	SystemdError string
}

// Collect enumerates every workload on this host. Linux only.
func Collect(ctx context.Context) Result {
	if runtime.GOOS != "linux" {
		return Result{}
	}

	var r Result
	containers, dockerOK, dockerErr := collectDocker(ctx)
	units, systemdOK, systemdErr := collectSystemd(ctx)

	r.DockerOK, r.DockerError = dockerOK, dockerErr
	r.SystemdOK, r.SystemdError = systemdOK, systemdErr
	r.Workloads = append(append([]Workload{}, containers...), units...)

	markProtected(r.Workloads)
	return r
}

// Hash fingerprints a workload set so an unchanged set never has to be sent.
//
// It sorts first: `docker ps` output ordering is not stable, and an
// ordering-sensitive hash would resend the full list every 60 seconds forever
// — a cost visible only as traffic.
//
// StartedAt is deliberately excluded: it does not change while a container
// runs, and including it would add nothing. Restarts IS included, because a
// container cycling is exactly the change worth reporting.
func Hash(wls []Workload) string {
	lines := make([]string, 0, len(wls))
	for _, w := range wls {
		lines = append(lines, strings.Join([]string{
			w.Kind, w.ID, w.Name, w.State, w.Health, w.Image, w.Stack,
			strconv.Itoa(w.Restarts),
		}, "\x00"))
	}
	sort.Strings(lines)
	h := sha256.New()
	for _, l := range lines {
		h.Write([]byte(l))
		h.Write([]byte("\n"))
	}
	return hex.EncodeToString(h.Sum(nil))
}
