//go:build linux

package web

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

	"gitea.dooplex.hu/admin/felhom-controller/internal/system"
)

// platformNetProbeFSClass is the real namespace classifier (statfs f_type) the probe child runs.
// Unbounded on purpose: the child's whole run is already bounded by the parent's netProbeTimeout.
func platformNetProbeFSClass(dir string) string {
	return system.ClassifyPathFS(dir)
}

// netProbeTimeout bounds one probe run (LAN write+readback is sub-second; a wedged share must not
// hold the orchestrator — the NFS soft/retry=0 options error out well inside this).
const netProbeTimeout = 30 * time.Second

// runNetProbe re-execs this binary as `felhom-controller --netprobe <dir>` with uid/gid 1000
// credentials (supplementary groups CLEARED — the probe must see exactly what a media app sees)
// and maps the exit code to a verdict. This is the production netProbeFn seam value.
func runNetProbe(ctx context.Context, dir string) probeOutcome {
	exe, err := os.Executable()
	if err != nil {
		return probeOutcome{OK: false, Category: "probe_io", Detail: "probe re-exec: executable path: " + err.Error()}
	}
	pctx, cancel := context.WithTimeout(ctx, netProbeTimeout)
	defer cancel()
	cmd := exec.CommandContext(pctx, exe, "--netprobe", dir)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Credential: &syscall.Credential{Uid: 1000, Gid: 1000, Groups: []uint32{}},
	}
	out, err := cmd.CombinedOutput()
	output := strings.TrimSpace(string(out))
	if err != nil {
		if ee, ok := err.(*exec.ExitError); ok {
			return netProbeVerdict(ee.ExitCode(), output)
		}
		// Spawn-level failure (EPERM on setuid = capability dropped somewhere — spike Q2 proved the
		// default container HAS the caps, so this is a real config regression worth the raw detail).
		return probeOutcome{OK: false, Category: "probe_io", Detail: "probe spawn failed: " + err.Error() + " | " + output}
	}
	return netProbeVerdict(0, output)
}
