// Tests for the /goal command's pure helpers: goalFollowUpDecision's branch
// logic (terminal states, token budget, turn cap, no-progress guard),
// parseGoalObjective / parseTokenBudget flag parsing, and goalTurnActivity's
// token/tool accounting.
package goal

import (
	"testing"

	"github.com/smallnest/pigo/internal/agentcore"
	"github.com/smallnest/pigo/internal/agenttool"
)

func TestGoalFollowUpDecision(t *testing.T) {
	tests := []struct {
		name     string
		snap     agenttool.GoalSnapshot
		wantCont bool
		wantTerm agenttool.GoalStatus
	}{
		{
			name:     "active continues",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalActive, Iterations: 1},
			wantCont: true,
			wantTerm: agenttool.GoalIdle,
		},
		{
			name:     "complete stops",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalComplete},
			wantCont: false,
			wantTerm: agenttool.GoalIdle,
		},
		{
			name:     "blocked stops",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalBlocked},
			wantCont: false,
			wantTerm: agenttool.GoalIdle,
		},
		{
			name:     "budget exhausted",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalActive, TokenBudget: 100, TokensUsed: 100},
			wantCont: false,
			wantTerm: agenttool.GoalBudgetLimited,
		},
		{
			name:     "budget under limit continues",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalActive, TokenBudget: 100, TokensUsed: 50},
			wantCont: true,
			wantTerm: agenttool.GoalIdle,
		},
		{
			name:     "turn cap",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalActive, Iterations: goalMaxAutomaticTurns},
			wantCont: false,
			wantTerm: agenttool.GoalPaused,
		},
		{
			name:     "no progress guard",
			snap:     agenttool.GoalSnapshot{Status: agenttool.GoalActive, NoProgress: goalMaxNoProgress},
			wantCont: false,
			wantTerm: agenttool.GoalPaused,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cont, term := goalFollowUpDecision(tt.snap)
			if cont != tt.wantCont {
				t.Errorf("cont = %v, want %v", cont, tt.wantCont)
			}
			if term != tt.wantTerm {
				t.Errorf("terminal = %q, want %q", term, tt.wantTerm)
			}
		})
	}
}

func TestParseGoalObjective(t *testing.T) {
	tests := []struct {
		name    string
		args    string
		wantObj string
		wantBud int
		wantErr bool
	}{
		{name: "no flag", args: "create hello.txt", wantObj: "create hello.txt", wantBud: 0},
		{name: "tokens k", args: "--tokens 100k build the thing", wantObj: "build the thing", wantBud: 100000},
		{name: "tokens m", args: "--tokens 1m do it", wantObj: "do it", wantBud: 1000000},
		{name: "tokens bare", args: "--tokens 5000 go", wantObj: "go", wantBud: 5000},
		{name: "flag only no objective", args: "--tokens 50k", wantObj: "", wantBud: 50000},
		{name: "bad value", args: "--tokens abc do it", wantErr: true},
		{name: "zero value", args: "--tokens 0 do it", wantErr: true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			obj, bud, err := parseGoalObjective(tt.args)
			if tt.wantErr {
				if err == nil {
					t.Fatalf("expected error, got obj=%q bud=%d", obj, bud)
				}
				return
			}
			if err != nil {
				t.Fatalf("unexpected error: %v", err)
			}
			if obj != tt.wantObj {
				t.Errorf("objective = %q, want %q", obj, tt.wantObj)
			}
			if bud != tt.wantBud {
				t.Errorf("budget = %d, want %d", bud, tt.wantBud)
			}
		})
	}
}

func TestGoalTurnActivity(t *testing.T) {
	tail := []agentcore.AgentMessage{
		agentcore.AssistantMessage{
			RoleField: agentcore.RoleAssistant,
			Usage:     &agentcore.Usage{OutputTokens: 40},
		},
		agentcore.AssistantMessage{
			RoleField: agentcore.RoleAssistant,
			Usage:     &agentcore.Usage{OutputTokens: 60},
		},
	}
	tokens, hadTool := goalTurnActivity(tail)
	if tokens != 100 {
		t.Errorf("tokens = %d, want 100", tokens)
	}
	if hadTool {
		t.Error("hadTool = true, want false (no tool calls or results)")
	}

	withTool := []agentcore.AgentMessage{
		agentcore.ToolResultMessage{ToolName: "bash"},
	}
	_, hadTool = goalTurnActivity(withTool)
	if !hadTool {
		t.Error("hadTool = false, want true (tool result present)")
	}
}
