package infra

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

// initDummyRepo creates a tiny git repo with a master branch and one commit so
// that `git worktree add ... master` can succeed.
func initDummyRepo(t *testing.T) string {
	t.Helper()
	dir := t.TempDir()

	runIn := func(name string, args ...string) {
		cmd := exec.Command(name, args...)
		cmd.Dir = dir
		// Detach from any global config that might inject signing/templates.
		cmd.Env = append(os.Environ(),
			"GIT_CONFIG_GLOBAL=/dev/null",
			"GIT_CONFIG_SYSTEM=/dev/null",
			"GIT_AUTHOR_NAME=test", "GIT_AUTHOR_EMAIL=t@t",
			"GIT_COMMITTER_NAME=test", "GIT_COMMITTER_EMAIL=t@t",
		)
		if out, err := cmd.CombinedOutput(); err != nil {
			t.Fatalf("%s %v: %v\n%s", name, args, err, out)
		}
	}

	runIn("git", "init", "-b", "master")
	if err := os.WriteFile(filepath.Join(dir, "README.md"), []byte("hi"), 0o644); err != nil {
		t.Fatal(err)
	}
	runIn("git", "add", "README.md")
	runIn("git", "commit", "-m", "init")

	return dir
}

func TestAgentLaunchWorktree_CreatesWorktreeAndBranch(t *testing.T) {
	repo := initDummyRepo(t)
	wt := filepath.Join(t.TempDir(), "wt-0001")
	log := filepath.Join(t.TempDir(), "claude.log")

	res := AgentLaunchWorktree(WorktreeLaunchConfig{
		RepoRoot:     repo,
		Branch:       "auto/test-0001",
		WorktreePath: wt,
		Prompt:       "hello",
		LogPath:      log,
	})

	if res.Error != "" {
		t.Fatalf("unexpected error: %s", res.Error)
	}
	if res.PID <= 0 {
		t.Fatalf("expected PID>0, got %d", res.PID)
	}
	if _, err := os.Stat(wt); err != nil {
		t.Fatalf("worktree dir missing: %v", err)
	}
	// Branch should exist in the main repo's refs.
	out, err := exec.Command("git", "-C", repo, "branch", "--list", "auto/test-0001").CombinedOutput()
	if err != nil || !strings.Contains(string(out), "auto/test-0001") {
		t.Fatalf("branch not created: err=%v out=%s", err, out)
	}
	if _, err := os.Stat(log); err != nil {
		t.Fatalf("log file missing: %v", err)
	}

	// Cleanup (best-effort, not asserted here).
	_ = AgentCleanupWorktree(repo, "auto/test-0001", wt, res.PID)
}

func TestAgentLaunchWorktree_ResetIfExists(t *testing.T) {
	repo := initDummyRepo(t)
	wt := filepath.Join(t.TempDir(), "wt-reset")
	log := filepath.Join(t.TempDir(), "claude.log")

	// First launch.
	res1 := AgentLaunchWorktree(WorktreeLaunchConfig{
		RepoRoot:     repo,
		Branch:       "auto/reset-test",
		WorktreePath: wt,
		Prompt:       "first",
		LogPath:      log,
	})
	if res1.Error != "" {
		t.Fatalf("first launch failed: %s", res1.Error)
	}

	// Second launch with ResetIfExists=true should succeed and recreate.
	res2 := AgentLaunchWorktree(WorktreeLaunchConfig{
		RepoRoot:      repo,
		Branch:        "auto/reset-test",
		WorktreePath:  wt,
		Prompt:        "second",
		LogPath:       log,
		ResetIfExists: true,
	})
	if res2.Error != "" {
		t.Fatalf("reset launch failed: %s", res2.Error)
	}
	if _, err := os.Stat(wt); err != nil {
		t.Fatalf("worktree dir missing after reset: %v", err)
	}

	_ = AgentCleanupWorktree(repo, "auto/reset-test", wt, res2.PID)
}

func TestAgentLaunchWorktree_MissingArgs(t *testing.T) {
	res := AgentLaunchWorktree(WorktreeLaunchConfig{})
	if res.Error == "" {
		t.Fatal("expected error for empty config, got none")
	}
}
