//go:build !windows

package infra

import (
	"fmt"
	"os/exec"
	"strings"
	"syscall"
	"time"
)

// AgentCleanupWorktree tears down a worktree previously created by
// AgentLaunchWorktree: kills the claude PID (SIGTERM, then SIGKILL after 1s),
// removes the git worktree (force) and deletes the branch.
//
// All three steps are best-effort; we only return an error when ALL three
// fail, so callers can call this on partially-initialised runs safely.
//
// Impure: signals processes, runs git, touches the filesystem.
func AgentCleanupWorktree(repoRoot, branch, worktreePath string, pid int) error {
	var killErr, wtErr, brErr error

	// 1. Kill the process tree if a PID was provided.
	if pid > 0 {
		if err := syscall.Kill(pid, syscall.SIGTERM); err != nil {
			killErr = err
		} else {
			// Give it ~1s to exit gracefully, then SIGKILL if still alive.
			time.Sleep(1 * time.Second)
			if alive := syscall.Kill(pid, 0); alive == nil {
				if err := syscall.Kill(pid, syscall.SIGKILL); err != nil {
					killErr = err
				}
			}
		}
	}

	// 2. Remove worktree (force).
	if worktreePath != "" {
		out, err := exec.Command("git", "-C", repoRoot, "worktree", "remove", "--force", worktreePath).CombinedOutput()
		if err != nil {
			wtErr = fmt.Errorf("worktree remove: %v: %s", err, strings.TrimSpace(string(out)))
		}
	}

	// 3. Delete the branch.
	if branch != "" {
		out, err := exec.Command("git", "-C", repoRoot, "branch", "-D", branch).CombinedOutput()
		if err != nil {
			brErr = fmt.Errorf("branch -D: %v: %s", err, strings.TrimSpace(string(out)))
		}
	}

	// Only error out if every requested step failed. Individual failures are
	// expected (e.g. cleanup called twice, dangling branch already gone).
	if killErr != nil && wtErr != nil && brErr != nil {
		return fmt.Errorf("cleanup failed: kill=%v; worktree=%v; branch=%v", killErr, wtErr, brErr)
	}
	return nil
}
