package runner_test

import (
	"context"
	"errors"
	"strings"
	"testing"

	"github.com/leonmika/wails-release/internal/runner"
)

func TestRealRunner_RunsCommandAndReturnsCombinedOutput(t *testing.T) {
	r := runner.Real{}
	out, err := r.Run(context.Background(), runner.Spec{Name: "echo", Args: []string{"hello"}})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !strings.Contains(string(out), "hello") {
		t.Fatalf("output %q does not contain 'hello'", out)
	}
}

func TestRealRunner_NonZeroExitReturnsError(t *testing.T) {
	r := runner.Real{}
	_, err := r.Run(context.Background(), runner.Spec{Name: "false"})
	if err == nil {
		t.Fatal("expected error from `false`, got nil")
	}
}

func TestFakeRunner_RecordsCallsAndReturnsConfiguredResult(t *testing.T) {
	f := &runner.Fake{}
	f.On("greet", []string{"alice"}).Return([]byte("hi alice"), nil)
	f.On("fail", nil).Return(nil, errors.New("boom"))

	out, err := f.Run(context.Background(), runner.Spec{Name: "greet", Args: []string{"alice"}})
	if err != nil || string(out) != "hi alice" {
		t.Fatalf("unexpected: out=%q err=%v", out, err)
	}

	_, err = f.Run(context.Background(), runner.Spec{Name: "fail"})
	if err == nil {
		t.Fatal("expected error from configured fake")
	}

	if len(f.Calls) != 2 {
		t.Fatalf("expected 2 calls, got %d", len(f.Calls))
	}
	if f.Calls[0].Name != "greet" || f.Calls[0].Args[0] != "alice" {
		t.Fatalf("unexpected first call: %+v", f.Calls[0])
	}
}

func TestFakeRunner_UnconfiguredCallFailsLoudly(t *testing.T) {
	f := &runner.Fake{}
	_, err := f.Run(context.Background(), runner.Spec{Name: "unknown"})
	if err == nil {
		t.Fatal("expected error for unconfigured call")
	}
}

func TestRealRunner_StdinIsPipedToCommand(t *testing.T) {
	r := runner.Real{}
	out, err := r.Run(context.Background(), runner.Spec{
		Name:  "cat",
		Stdin: []byte("piped-payload"),
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !strings.Contains(string(out), "piped-payload") {
		t.Fatalf("output %q does not contain piped payload", out)
	}
}

func TestRealRunner_DirSetsWorkingDirectory(t *testing.T) {
	dir := t.TempDir()
	r := runner.Real{}
	out, err := r.Run(context.Background(), runner.Spec{
		Name: "pwd",
		Dir:  dir,
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	// macOS resolves /var/folders/... → /private/var/folders/... so just
	// match the trailing tempdir name.
	if !strings.Contains(string(out), dir[strings.LastIndex(dir, "/"):]) {
		t.Fatalf("pwd output %q does not contain %q", out, dir)
	}
}

func TestRealRunner_EnvReplacesProcessEnv(t *testing.T) {
	r := runner.Real{}
	out, err := r.Run(context.Background(), runner.Spec{
		Name: "sh",
		Args: []string{"-c", "echo $WAILS_TEST"},
		Env:  []string{"WAILS_TEST=hello-from-spec-env"},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !strings.Contains(string(out), "hello-from-spec-env") {
		t.Fatalf("output %q does not contain expected env value", out)
	}
}
