package infra

import (
	"strings"
	"testing"
)

func TestProcessSpawn(t *testing.T) {
	t.Run("spawn and wait echo", func(t *testing.T) {
		h, err := ProcessSpawn("echo hello", "", nil, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		res, err := ProcessWait(h, 10)
		if err != nil {
			t.Fatalf("wait: %v", err)
		}
		if res.ExitCode != 0 {
			t.Errorf("exit code: got %d, want 0", res.ExitCode)
		}
		if !strings.Contains(res.Stdout, "hello") {
			t.Errorf("stdout: got %q, want it to contain 'hello'", res.Stdout)
		}
	})

	t.Run("spawn with timeout kills", func(t *testing.T) {
		h, err := ProcessSpawn("sleep 60", "", nil, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		res, err := ProcessWait(h, 2)
		if err != nil {
			t.Fatalf("wait: %v", err)
		}
		if !res.Killed {
			t.Errorf("killed: got false, want true")
		}
		if res.ExitCode == 0 {
			t.Errorf("exit code: got 0, want != 0 after kill")
		}
	})

	t.Run("spawn with env", func(t *testing.T) {
		h, err := ProcessSpawn("echo $TEST_VAR", "", []string{"PATH=/usr/bin:/bin", "TEST_VAR=hello123"}, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		res, err := ProcessWait(h, 10)
		if err != nil {
			t.Fatalf("wait: %v", err)
		}
		if !strings.Contains(res.Stdout, "hello123") {
			t.Errorf("stdout: got %q, want it to contain 'hello123'", res.Stdout)
		}
	})

	t.Run("spawn script", func(t *testing.T) {
		script := "#!/bin/sh\necho line1\necho line2"
		h, err := ProcessSpawn(script, "", nil, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		res, err := ProcessWait(h, 10)
		if err != nil {
			t.Fatalf("wait: %v", err)
		}
		if !strings.Contains(res.Stdout, "line1") {
			t.Errorf("stdout: got %q, want it to contain 'line1'", res.Stdout)
		}
		if !strings.Contains(res.Stdout, "line2") {
			t.Errorf("stdout: got %q, want it to contain 'line2'", res.Stdout)
		}
	})

	t.Run("spawn with working dir", func(t *testing.T) {
		h, err := ProcessSpawn("pwd", "/tmp", nil, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		res, err := ProcessWait(h, 10)
		if err != nil {
			t.Fatalf("wait: %v", err)
		}
		if !strings.Contains(res.Stdout, "/tmp") {
			t.Errorf("stdout: got %q, want it to contain '/tmp'", res.Stdout)
		}
	})

	t.Run("kill process", func(t *testing.T) {
		h, err := ProcessSpawn("sleep 60", "", nil, "")
		if err != nil {
			t.Fatalf("spawn: %v", err)
		}
		if err := ProcessKill(h, 1); err != nil {
			t.Fatalf("kill: %v", err)
		}
		// After kill, Wait should unblock quickly.
		_ = h.Cmd.Wait()
		state := h.Cmd.ProcessState
		if state == nil {
			t.Fatal("process state is nil after kill+wait")
		}
		if state.ExitCode() == 0 {
			t.Errorf("exit code: got 0 after kill, want non-zero")
		}
	})
}
