// Package proc 提供跨平台的"进程组/进程树"终止抽象。一个 Group 把某个进程及其
// 派生的所有子孙进程作为单一单元管理，使 stop/restart/crash 时能整树清理，避免
// dev server（如 pnpm dev → node/vite/esbuild）留下占用端口的孤儿进程。
//
// 用法与 *exec.Cmd 生命周期对齐：
//
//	g := proc.NewGroup()
//	g.Prepare(cmd)        // cmd.Start() 之前：Unix 设置 SysProcAttr.Setpgid
//	cmd.Start()
//	g.Adopt(cmd)          // cmd.Start() 之后：Windows 创建 Job 并 Assign
//	...
//	g.TerminateGroup(done, grace)  // 整树优雅终止
//	g.Close()             // 释放平台句柄
package proc

import (
	"os/exec"
	"time"
)

// Group 抽象"一个进程及其所有子孙进程"作为单一单元管理。
// 非并发安全：调用方需保证 Prepare/Adopt/TerminateGroup/Close 的串行使用
// （RunSupervisor / ACP Supervisor 已用各自的锁与 done channel 保证）。
type Group interface {
	// Prepare 在 cmd.Start() 之前设置平台属性（Unix: SysProcAttr.Setpgid）。
	Prepare(cmd *exec.Cmd)
	// Adopt 在 cmd.Start() 之后接管已启动的进程（Windows: 创建 Job 并
	// AssignProcessToJobObject）。Unix 为记录 pgid。必须在子进程派生前调用。
	Adopt(cmd *exec.Cmd) error
	// TerminateGroup 优雅终止整组：Unix 先 SIGTERM(-pgid) 等 grace 再 SIGKILL(-pgid)；
	// Windows CloseHandle(job) 触发 KILL_ON_JOB_CLOSE 整树终止。
	// done 由调用方（monitor goroutine）关闭，用于感知优雅退出、提前返回。
	TerminateGroup(done <-chan struct{}, grace time.Duration)
	// Close 释放平台句柄（Windows: 关闭 Job handle；Unix: no-op）。幂等。
	Close()
}

// NewGroup 按编译期 build tag 返回 unixGroup / windowsGroup。
func NewGroup() Group { return newGroup() }
