//go:build windows

package platform

import (
	"os"
	"syscall"

	"golang.org/x/sys/windows"
)

// stillActive is the exit code GetExitCodeProcess reports while a
// process is still running (Win32 STILL_ACTIVE / STATUS_PENDING).
const stillActive = 259

// ShutdownSignals returns the signals a long-running process should trap
// to begin a graceful shutdown. Windows has no SIGTERM; os.Interrupt —
// delivered for Ctrl-C and Ctrl-Break — is the only portable trigger.
func ShutdownSignals() []os.Signal {
	return []os.Signal{os.Interrupt}
}

// ProcessAlive reports whether a process with the given PID currently
// exists and has not yet exited. It opens a query handle and inspects
// the exit code: only a still-running process reports STILL_ACTIVE.
func ProcessAlive(pid int) bool {
	if pid <= 0 {
		return false
	}
	h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
	if err != nil {
		return false
	}
	defer windows.CloseHandle(h) //nolint:errcheck // best-effort handle close
	var code uint32
	if err := windows.GetExitCodeProcess(h, &code); err != nil {
		return false
	}
	return code == stillActive
}

// TerminateProcess asks the process to exit. Windows offers no graceful
// signal a console-less detached process can receive, so this is a hard
// TerminateProcess — the same as KillProcess. The daemon's preferred
// stop path is the control-socket RPC; this is only the fallback for a
// daemon that no longer answers the socket.
func TerminateProcess(pid int) error {
	return KillProcess(pid)
}

// KillProcess forcibly terminates the process.
func KillProcess(pid int) error {
	if pid <= 0 {
		return nil
	}
	p, err := os.FindProcess(pid)
	if err != nil {
		return err
	}
	return p.Kill()
}

// DetachSysProcAttr returns the SysProcAttr that fully detaches a
// spawned child: a new process group, so a Ctrl-C in the parent console
// isn't forwarded, plus DETACHED_PROCESS so the child runs with no
// inherited console.
func DetachSysProcAttr() *syscall.SysProcAttr {
	return &syscall.SysProcAttr{
		CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.DETACHED_PROCESS,
	}
}
