package exec

import (
	"sort"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/internal/agentview"
)

// agentExecSnapshot is the deliberately smaller public projection used by the
// Exec Agent list/get actions. agentview.Snapshot is also used by local UI
// APIs, so it may carry configuration details that are not safe on the
// model-facing Exec boundary. In particular, this type has no credential
// values, URL, endpoint, source identifier, or raw filesystem path fields.
type agentExecSnapshot struct {
	ID                    string           `json:"id"`
	Name                  string           `json:"name,omitempty"`
	Runtime               string           `json:"runtime"`
	Description           string           `json:"description,omitempty"`
	Labels                []string         `json:"labels,omitempty"`
	APIKeyConfigured      bool             `json:"apiKeyConfigured,omitempty"`
	ConfiguredHeaderNames []string         `json:"configuredHeaderNames,omitempty"`
	WireAPI               string           `json:"wireApi,omitempty"`
	Model                 string           `json:"model,omitempty"`
	SmallModel            string           `json:"smallModel,omitempty"`
	ReasoningEffort       string           `json:"reasoningEffort,omitempty"`
	Policy                *agentExecPolicy `json:"policy,omitempty"`
	RuntimeType           string           `json:"runtimeType,omitempty"`
	Status                string           `json:"status"`
	BackendRegistered     bool             `json:"backendRegistered"`
	SourceType            string           `json:"sourceType,omitempty"`
	SourceName            string           `json:"sourceName,omitempty"`
}

type agentExecPolicy struct {
	MaxConcurrentTasks int    `json:"maxConcurrentTasks,omitempty"`
	Timeout            string `json:"timeout,omitempty"`
	AllowedPathCount   int    `json:"allowedPathCount,omitempty"`
}

func projectAgentSnapshot(snapshot agentview.Snapshot) agentExecSnapshot {
	projected := agentExecSnapshot{
		ID:                snapshot.ID,
		Name:              snapshot.Name,
		Runtime:           snapshot.Runtime,
		Description:       snapshot.Description,
		Labels:            append([]string(nil), snapshot.Labels...),
		APIKeyConfigured:  snapshot.APIKeyConfigured,
		WireAPI:           snapshot.WireAPI,
		Model:             snapshot.Model,
		SmallModel:        snapshot.SmallModel,
		ReasoningEffort:   snapshot.ReasoningEffort,
		RuntimeType:       snapshot.RuntimeType,
		Status:            snapshot.Status,
		BackendRegistered: snapshot.BackendRegistered,
		SourceType:        snapshot.SourceType,
		SourceName:        snapshot.SourceName,
	}
	if len(snapshot.Headers) > 0 {
		projected.ConfiguredHeaderNames = make([]string, 0, len(snapshot.Headers))
		for name := range snapshot.Headers {
			name = strings.ToLower(strings.TrimSpace(name))
			if name != "" {
				projected.ConfiguredHeaderNames = append(projected.ConfiguredHeaderNames, name)
			}
		}
		sort.Strings(projected.ConfiguredHeaderNames)
		projected.ConfiguredHeaderNames = uniqueStrings(projected.ConfiguredHeaderNames)
	}
	if snapshot.Policy != nil {
		projected.Policy = &agentExecPolicy{
			MaxConcurrentTasks: snapshot.Policy.MaxConcurrentSessions,
			Timeout:            snapshot.Policy.Timeout,
			AllowedPathCount:   len(snapshot.Policy.AllowedPaths),
		}
	}
	return projected
}

func uniqueStrings(values []string) []string {
	if len(values) < 2 {
		return values
	}
	out := values[:1]
	for _, value := range values[1:] {
		if value != out[len(out)-1] {
			out = append(out, value)
		}
	}
	return out
}
