package agentview

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/desktop/internal/agent"
	"github.com/tidbcloud/AgentTeam/desktop/internal/types"
)

func TestBuildProjectsSnapshot(t *testing.T) {
	labels := []string{"backend"}
	headers := map[string]string{"X-Team": "platform"}
	paths := []string{"/workspace"}
	configured := agent.Config{
		ID: "agent-1", Name: "Agent One", Runtime: "codex", Description: "backend agent",
		Labels: labels, BaseURL: " https://model.example/v1 ", APIKey: "secret", Headers: headers,
		WireAPI: " responses ", Model: "gpt", SmallModel: "mini", ReasoningEffort: "high",
		Policy: agent.Policy{MaxConcurrentSessions: 2, Timeout: "30m", AllowedPaths: paths},
		Source: agent.NewAgentTeamSource("server-1"),
	}
	got := Build(configured, BuildContext{
		SourceName: "Primary", RuntimeType: "codex",
	})
	require.Equal(t, Snapshot{
		ID: "agent-1", Name: "Agent One", Runtime: "codex", Description: "backend agent",
		Labels: []string{"backend"}, BaseURL: "https://model.example/v1", APIKeyConfigured: true,
		Headers: Headers{"X-Team": "platform"}, WireAPI: "responses", Model: "gpt", SmallModel: "mini",
		ReasoningEffort: "high",
		Policy:          &Policy{MaxConcurrentSessions: 2, Timeout: "30m", AllowedPaths: []string{"/workspace"}},
		RuntimeType:     "codex", Status: "registered", BackendRegistered: true,
		Source: "agentteam:server-1", SourceType: "agentteam", SourceName: "Primary",
	}, got)

	labels[0] = "mutated"
	headers["X-Team"] = "mutated"
	paths[0] = "/mutated"
	require.Equal(t, []string{"backend"}, got.Labels)
	require.Equal(t, Headers{"X-Team": "platform"}, got.Headers)
	require.Equal(t, []string{"/workspace"}, got.Policy.AllowedPaths)
}

func TestBuildPreservesOptionalJSONShape(t *testing.T) {
	got := Build(agent.Config{ID: "local", Runtime: "builtin", Labels: []string{}, Headers: map[string]string{}}, BuildContext{})
	encoded, err := json.Marshal(got)
	require.NoError(t, err)
	require.JSONEq(t, `{
		"id":"local","runtime":"builtin","status":"pending-registration","backendRegistered":false
	}`, string(encoded))
	require.Nil(t, got.Policy)
	require.Nil(t, got.Labels)
	require.Nil(t, got.Headers)
}

func TestBuildSessionOverlay(t *testing.T) {
	configured := agent.Config{ID: "local", Runtime: "codex", Source: agent.NewLocalSource()}
	tests := []struct {
		name           string
		session        *types.SessionSnapshot
		wantStatus     string
		wantRegistered bool
	}{
		{name: "no session", wantStatus: "pending-registration"},
		{name: "stopped", session: &types.SessionSnapshot{ServerAgentID: "server-agent", Status: " stopped "}, wantStatus: "pending-registration", wantRegistered: true},
		{name: "inactive", session: &types.SessionSnapshot{Status: "inactive"}, wantStatus: "pending-registration"},
		{name: "active empty status", session: &types.SessionSnapshot{}, wantStatus: "active"},
		{name: "active explicit status", session: &types.SessionSnapshot{Status: " running "}, wantStatus: "running"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := Build(configured, BuildContext{Session: tt.session})
			require.Equal(t, tt.wantStatus, got.Status)
			require.Equal(t, tt.wantRegistered, got.BackendRegistered)
		})
	}
}

func TestBuildDoesNotExposeDefaultLLMFields(t *testing.T) {
	got := Build(agent.Config{ID: "agent", Runtime: "codex", BaseURL: "  ", APIKey: "  ", Headers: map[string]string{}, WireAPI: "  "}, BuildContext{})
	require.Empty(t, got.BaseURL)
	require.False(t, got.APIKeyConfigured)
	require.Nil(t, got.Headers)
	require.Empty(t, got.WireAPI)
}
