package dispatcher

import (
	"strings"

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

func runtimeEventTrajectoryEntries(ev runtimeevents.Event) []types.TrajectoryEntry {
	var entries []types.TrajectoryEntry
	activity, detail := runtimeEventActivity(ev)

	switch ev.Kind {
	case runtimeevents.KindDeliveryPending:
		text := strings.TrimSpace(payloadText(ev))
		metadata := runtimeEventDeliveryMetadata(ev, "pending", false)
		if text != "" {
			entries = append(entries, types.TrajectoryEntry{
				Kind:       consts.ParsedEventKindPromptInput,
				Text:       text,
				PromptKind: firstNonEmpty(payloadString(ev, "prompt_kind"), consts.PromptKindDeliveryText),
				Runtime:    strings.TrimSpace(ev.Context.Runtime),
				EventType:  strings.TrimSpace(payloadString(ev, "event_type")),
				Metadata:   metadata,
			})
			break
		}
		detail = firstNonEmpty(runtimeEventDetail(ev), detail, "New message delivered to agent.")
		entries = append(entries, types.TrajectoryEntry{
			Kind:     consts.TrajectoryKindStatus,
			Activity: "message delivered",
			Detail:   detail,
			Metadata: metadata,
		})
	case runtimeevents.KindDeliveryAcked:
		detail = firstNonEmpty(runtimeEventDetail(ev), detail, "Agent acknowledged message input.")
		entries = append(entries, types.TrajectoryEntry{
			Kind:     consts.TrajectoryKindStatus,
			Activity: "agent ack",
			Detail:   detail,
			Metadata: runtimeEventDeliveryMetadata(ev, "surfaced", true),
		})
	case runtimeevents.KindTurnThinking:
		if text := payloadText(ev); strings.TrimSpace(text) != "" {
			entries = append(entries, types.TrajectoryEntry{
				Kind:      consts.ParsedEventKindThinking,
				Text:      text,
				Title:     payloadString(ev, "title"),
				SectionID: payloadString(ev, "section_id", "sectionId"),
			})
		}
	case runtimeevents.KindTurnText:
		if text := payloadText(ev); strings.TrimSpace(text) != "" {
			entries = append(entries, types.TrajectoryEntry{
				Kind: consts.ParsedEventKindText,
				Text: text,
			})
		}
	case runtimeevents.KindTurnToolCall:
		inputStr := payloadToolInput(ev)
		entries = append(entries, types.TrajectoryEntry{
			Kind:       consts.TrajectoryKindToolStart,
			ToolName:   runtimeEventToolName(ev),
			ToolCallID: runtimeEventToolCallID(ev),
			ToolInput:  inputStr,
			Metadata:   runtimeEventToolMetadata(ev),
		})
	case runtimeevents.KindTurnToolOutput:
		if text := payloadToolInput(ev); strings.TrimSpace(text) != "" {
			entries = append(entries, types.TrajectoryEntry{
				Kind:       consts.ParsedEventKindToolOutput,
				ToolName:   runtimeEventToolName(ev),
				ToolCallID: runtimeEventToolCallID(ev),
				Text:       text,
				Metadata:   runtimeEventToolMetadata(ev),
			})
		}
	case runtimeevents.KindTurnSubagentActivity:
		if entry, ok := runtimeEventSubagentActivityEntry(ev); ok {
			entries = append(entries, entry)
		}
	case runtimeevents.KindTurnCompacted:
		// The activity entry appended below is the participant-visible terminal
		// compaction record. Do not duplicate it as assistant text.
	case runtimeevents.KindTurnError:
		message := firstNonEmpty(payloadString(ev, "message", "error"), payloadText(ev), runtimeEventDetail(ev))
		entries = append(entries, types.TrajectoryEntry{
			Kind:     consts.ParsedEventKindText,
			Text:     "Error: " + message,
			Metadata: payloadMetadata(ev),
		})
	case runtimeevents.KindPromptInput:
		entries = append(entries, types.TrajectoryEntry{
			Kind:       consts.ParsedEventKindPromptInput,
			Text:       payloadText(ev),
			PromptKind: payloadString(ev, "prompt_kind"),
			Runtime:    firstNonEmpty(ev.Context.Runtime, payloadString(ev, "runtime")),
			EventType:  payloadString(ev, "event_type"),
		})
	case runtimeevents.KindUsageTokens:
		if data, ok := runtimeevents.DataAs[*runtimeevents.UsageTokensData](ev); ok &&
			(data.ActiveContextTokens > 0 || data.ContextWindowTokens > 0) {
			entries = append(entries, types.TrajectoryEntry{
				Kind:                consts.TrajectoryKindContextUsage,
				SessionID:           strings.TrimSpace(ev.Context.SessionID),
				ActiveContextTokens: data.ActiveContextTokens,
				ContextWindowTokens: data.ContextWindowTokens,
			})
		}
	default:
		if fallback, ok := runtimeEventFallbackTrajectoryEntry(ev); ok {
			entries = append(entries, fallback)
		}
	}

	if activity != "" && ev.Kind != runtimeevents.KindTurnText && ev.Kind != runtimeevents.KindTurnThinking {
		entries = append(entries, types.TrajectoryEntry{
			Kind:     consts.TrajectoryKindStatus,
			Activity: activity,
			Detail:   detail,
		})
	}
	return entries
}

func runtimeEventSubagentActivityEntry(ev runtimeevents.Event) (types.TrajectoryEntry, bool) {
	detail := strings.TrimSpace(runtimeEventDetail(ev))
	if detail == "" {
		return types.TrajectoryEntry{}, false
	}
	return types.TrajectoryEntry{
		Kind:      consts.TrajectoryKindStatus,
		Activity:  "working",
		Detail:    detail,
		Runtime:   strings.TrimSpace(ev.Context.Runtime),
		EventType: payloadString(ev, "event_type"),
		Metadata:  cloneTrajectoryMetadata(payloadMetadata(ev)),
	}, true
}

func runtimeEventFallbackTrajectoryEntry(ev runtimeevents.Event) (types.TrajectoryEntry, bool) {
	if !strings.HasPrefix(string(ev.Kind), "turn.") {
		return types.TrajectoryEntry{}, false
	}
	if text := payloadText(ev); strings.TrimSpace(text) != "" {
		return types.TrajectoryEntry{Kind: consts.ParsedEventKindText, Text: text}, true
	}
	toolName := runtimeEventToolName(ev)
	toolInput := payloadToolInput(ev)
	if strings.TrimSpace(toolName) != "" || strings.TrimSpace(toolInput) != "" {
		return types.TrajectoryEntry{
			Kind:       consts.TrajectoryKindToolStart,
			ToolName:   toolName,
			ToolCallID: runtimeEventToolCallID(ev),
			ToolInput:  toolInput,
		}, true
	}
	if detail := runtimeEventDetail(ev); strings.TrimSpace(detail) != "" {
		return types.TrajectoryEntry{Kind: consts.TrajectoryKindStatus, Activity: "working", Detail: detail}, true
	}
	return types.TrajectoryEntry{}, false
}
