package terminal

import (
	"io"
	"os"
	"os/exec"
	"strings"

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

// 终端窗口的兜底尺寸（前端尚未上报 resize 前使用）。
const (
	defaultRows uint16 = 24
	defaultCols uint16 = 80
)

// ptySession 持有平台相关的 shell 进程与 IO。resizeFn 由 startPTY 注入：
// Unix 调 pty.Setsize，Windows 为 nil（降级实现无 resize）。这样 ptySession
// 类型与生命周期方法可保持平台无关，仅 startPTY 按 build tag 特化。
type ptySession struct {
	cmd      *exec.Cmd
	group    procgrp.Group
	rw       io.ReadWriteCloser // PTY master（Unix）或 stdio 桥接（Windows）
	resizeFn func(rows, cols uint16) error
}

func (p *ptySession) resize(rows, cols uint16) error {
	if p.resizeFn == nil {
		return nil
	}
	return p.resizeFn(rows, cols)
}

// terminate 是 Open 失败路径的尽力清理（kill 进程、释放句柄、关闭 IO）。
// 正常关闭走 Supervisor.Close → group.TerminateGroup 的整树终止。
func (p *ptySession) terminate() {
	if p.cmd.Process != nil {
		_ = p.cmd.Process.Kill()
	}
	p.group.Close()
	_ = p.rw.Close()
}

// buildEnv 从宿主环境按白名单过滤出传给 shell 的环境变量，并补上 TERM 以便
// 终端程序正确渲染。白名单确保 APP_MASTER_KEY、DB DSN、git 凭据等敏感变量
// 不会透传给交互式 shell。
func buildEnv(whitelist []string) []string {
	allow := make(map[string]bool, len(whitelist))
	for _, k := range whitelist {
		allow[k] = true
	}
	out := make([]string, 0, len(whitelist)+1)
	hasTerm := false
	for _, kv := range os.Environ() {
		i := strings.IndexByte(kv, '=')
		if i < 0 {
			continue
		}
		name := kv[:i]
		if !allow[name] {
			continue
		}
		if name == "TERM" {
			hasTerm = true
		}
		out = append(out, kv)
	}
	if !hasTerm {
		out = append(out, "TERM=xterm-256color")
	}
	return out
}
