//go:build !windows

package terminal

import (
	"os/exec"

	"github.com/creack/pty"

	procgrp "github.com/yan1h/agent-coding-workflow/internal/infra/proc"
)

// startPTY 在真 PTY 中拉起 shell（Unix）。
//
// 关于进程组：pty.StartWithSize 内部会设置 SysProcAttr.Setsid，使 shell 成为新
// 会话的首进程，其进程组 pgid == pid。因此这里**不**调用 group.Prepare（它设的
// Setpgid 与 Setsid 同时设置在 Go exec 下是非法/冗余的）；group.Adopt 直接记录
// pgid = cmd.Process.Pid，TerminateGroup 向 -pgid 发信号即可整树终止 shell 及其
// 派生的全部子孙进程。
func startPTY(shell string, env []string, rows, cols uint16) (*ptySession, error) {
	cmd := exec.Command(shell)
	cmd.Env = env

	ptmx, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: rows, Cols: cols})
	if err != nil {
		return nil, err
	}

	group := procgrp.NewGroup()
	if err := group.Adopt(cmd); err != nil {
		_ = ptmx.Close()
		if cmd.Process != nil {
			_ = cmd.Process.Kill()
		}
		return nil, err
	}

	return &ptySession{
		cmd:   cmd,
		group: group,
		rw:    ptmx,
		resizeFn: func(r, c uint16) error {
			return pty.Setsize(ptmx, &pty.Winsize{Rows: r, Cols: c})
		},
	}, nil
}
