package orchestrator

import "sync"

// EnrichmentData holds async sub-session results stored for the next user turn.
type EnrichmentData struct {
	MemorySummary  string
	ThoughtOutline string
	IoTSummary     string
	KnowledgeInfo  string

	// Pending tool results from async execution (keyed by tool call ID)
	PendingToolResults []PendingToolResult
}

// PendingToolResult holds the result of a tool that completed asynchronously.
type PendingToolResult struct {
	ToolCallID  string `json:"tool_call_id"`
	ToolName    string `json:"tool_name"`
	Result      string `json:"result"`
	Success     bool   `json:"success"`
	SessionID   string `json:"session_id,omitempty"`
	UserID      string `json:"user_id,omitempty"`
	Platform    string `json:"platform,omitempty"`     // 来源平台
	ChannelID   string `json:"channel_id,omitempty"`   // 来源频道
	ChannelType string `json:"channel_type,omitempty"` // direct/group
}

// SessionEnrichmentStore is a thread-safe per-session cache for async
// sub-session enrichment. Results from the current turn are stored here
// and injected at the start of the next turn's synthesis.
type SessionEnrichmentStore struct {
	mu   sync.RWMutex
	data map[string]*EnrichmentData
}

// NewEnrichmentStore creates a new SessionEnrichmentStore.
func NewEnrichmentStore() *SessionEnrichmentStore {
	return &SessionEnrichmentStore{
		data: make(map[string]*EnrichmentData),
	}
}

// Get returns stored enrichment for a session (does NOT clear; results may be reused).
func (s *SessionEnrichmentStore) Get(sessionID string) *EnrichmentData {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.data[sessionID]
}

// Pop returns stored enrichment for a session and clears it (one-shot consumption).
func (s *SessionEnrichmentStore) Pop(sessionID string) *EnrichmentData {
	s.mu.Lock()
	defer s.mu.Unlock()
	d, ok := s.data[sessionID]
	if ok {
		delete(s.data, sessionID)
	}
	return d
}

// Store saves enrichment for a session (called when sub-sessions complete).
func (s *SessionEnrichmentStore) Store(sessionID string, d *EnrichmentData) {
	if d == nil {
		return
	}
	s.mu.Lock()
	s.data[sessionID] = d
	s.mu.Unlock()
}

// AppendToolResult adds a completed tool result to the session's enrichment data.
func (s *SessionEnrichmentStore) AppendToolResult(sessionID string, r PendingToolResult) {
	s.mu.Lock()
	defer s.mu.Unlock()
	d, ok := s.data[sessionID]
	if !ok {
		d = &EnrichmentData{}
		s.data[sessionID] = d
	}
	d.PendingToolResults = append(d.PendingToolResults, r)
}

// ---- Global pending tool store (used by Synthesizer for async tool results) ----

var globalPendingToolStore *SessionEnrichmentStore
var pendingToolStoreOnce sync.Once

// InitGlobalPendingToolStore initializes the singleton.
func InitGlobalPendingToolStore() {
	pendingToolStoreOnce.Do(func() {
		globalPendingToolStore = NewEnrichmentStore()
	})
}

// GetGlobalPendingToolStore returns the singleton, or nil if not initialized.
func GetGlobalPendingToolStore() *SessionEnrichmentStore {
	return globalPendingToolStore
}
