package metrics

import (
	"context"
	"log/slog"
	"sync"
	"sync/atomic"
)

var (
	initOnce                sync.Once
	globalTSDB              *TSDBCollector
	globalTokenTracking     *TokenTrackingStore
	globalTokenAudit        *tokenTrackingAuditWriter
	serverMessages          *ServerMessageCollector
	collector               Collector
	detailedTokenCollection atomic.Bool
)

// Init initializes the global metrics singletons (TSDB, server message collector, LLM collector).
// It is safe to call multiple times; only the first call will perform initialization.
func Init(ctx context.Context) {
	initOnce.Do(func() {
		t, err := NewTSDBCollector()
		if err != nil {
			slog.Warn("failed to open TSDB for statistics, stats will not be persisted", "error", err)
		}
		globalTSDB = t

		tokenTracking, tokenTrackingErr := NewTokenTrackingStore()
		if tokenTrackingErr != nil {
			slog.Warn("failed to open token tracking TSDB, token source data will not be persisted", "error", tokenTrackingErr)
		}
		globalTokenTracking = tokenTracking

		tokenAudit, tokenAuditErr := newTokenTrackingAuditWriter()
		if tokenAuditErr != nil {
			slog.Warn("failed to open token tracking audit, diagnostic data will not be persisted", "error", tokenAuditErr)
		}
		globalTokenAudit = tokenAudit

		serverMessages = NewServerMessageCollector(globalTSDB)
		serverMessages.Start(ctx)

		if globalTSDB != nil {
			collector = NewCollectorWithTSDB(globalTSDB)
			collector.Start(ctx)
		}
	})
}

// DefaultServerMessageCollector returns the global server message stats collector singleton.
// Returns nil if not initialized.
func DefaultServerMessageCollector() *ServerMessageCollector {
	return serverMessages
}

// SetDetailedTokenCollectionEnabled controls the process-lifetime,
// high-cardinality token diagnosis recorder. It is intentionally not persisted.
func SetDetailedTokenCollectionEnabled(enabled bool) {
	detailedTokenCollection.Store(enabled)
}

// DetailedTokenCollectionEnabled reports the current daemon-lifetime state.
func DetailedTokenCollectionEnabled() bool {
	return detailedTokenCollection.Load()
}

// DefaultPromptAttributionRecorder returns the opt-in prompt-attribution write
// path.
func DefaultPromptAttributionRecorder() PromptAttributionRecorder {
	if !DetailedTokenCollectionEnabled() {
		return nil
	}
	return globalTSDB
}

// DefaultTokenAnalysisRecorder returns the full opt-in detailed recorder.
func DefaultTokenAnalysisRecorder() TokenAnalysisRecorder {
	if !DetailedTokenCollectionEnabled() {
		return nil
	}
	return globalTSDB
}

// DefaultTokenAnalysisQuerier returns the live daemon-owned detailed-evidence
// query path.
func DefaultTokenAnalysisQuerier() TokenAnalysisQuerier {
	return globalTSDB
}

// DefaultTokenTrackingRecorder returns the global sanitized token-source recorder.
func DefaultTokenTrackingRecorder() TokenSourceRecorder {
	return globalTokenTracking
}

// DefaultTokenTrackingQuerier returns the global Machine Dashboard token-source querier.
func DefaultTokenTrackingQuerier() TokenSourceQuerier {
	return globalTokenTracking
}

// DefaultTokenTrackingAuditRecorder returns the local diagnostic audit recorder.
func DefaultTokenTrackingAuditRecorder() TokenTrackingAuditRecorder {
	return globalTokenAudit
}

// DefaultCollector returns the global LLM stats collector singleton.
// Returns nil if not initialized.
func DefaultCollector() Collector {
	return collector
}

// DefaultRequestRecorder returns the write-only LLM request recorder singleton.
func DefaultRequestRecorder() RequestRecorder {
	return collector
}

// DefaultErrorRecorder returns the write-only LLM error recorder singleton.
func DefaultErrorRecorder() ErrorRecorder {
	return collector
}

// DefaultStatsQuerier returns the aggregate LLM stats query singleton.
func DefaultStatsQuerier() StatsQuerier {
	return collector
}

// DefaultTimeSeriesQuerier returns the LLM time-series query singleton.
func DefaultTimeSeriesQuerier() TimeSeriesQuerier {
	return collector
}

// DefaultErrorQuerier returns the LLM error query singleton.
func DefaultErrorQuerier() ErrorQuerier {
	return collector
}

// DefaultServiceStatusQuerier returns the LLM service status query singleton.
func DefaultServiceStatusQuerier() ServiceStatusQuerier {
	return collector
}

// DefaultLifecycle returns the LLM collector lifecycle singleton.
func DefaultLifecycle() Lifecycle {
	return collector
}

// CloseTSDB closes the global TSDB instance if it is open.
func CloseTSDB() {
	if globalTokenAudit != nil {
		if err := globalTokenAudit.Close(); err != nil {
			slog.Warn("failed to close token tracking audit", "error", err)
		}
	}
	if globalTokenTracking != nil {
		if err := globalTokenTracking.Close(); err != nil {
			slog.Warn("failed to close token tracking TSDB", "error", err)
		}
	}
	if globalTSDB != nil {
		if err := globalTSDB.Close(); err != nil {
			slog.Warn("failed to close statistics TSDB", "error", err)
		}
	}
}
