package stats

import (
	"sync"
	"time"
)

// ComponentStats represents statistics for a specific component
type ComponentStats struct {
	Component   string    `json:"component"`
	Timestamp   time.Time `json:"timestamp"`
	Queries     int64     `json:"queries"`
	Errors      int64     `json:"errors"`
	ResponseTime float64  `json:"response_time_ms"`
	Connections int64     `json:"connections"`
	BytesServed int64     `json:"bytes_served"`
	Metadata    map[string]interface{} `json:"metadata"`
}

// DHTStats represents DHT-specific statistics
type DHTStats struct {
	QueriesSent     int64     `json:"queries_sent"`
	QueriesReceived int64     `json:"queries_received"`
	NodesInTable    int       `json:"nodes_in_routing_table"`
	StoredPeers     int       `json:"stored_peers"`
	AnnouncesSent   int64     `json:"announces_sent"`
	PeersSeen       int64     `json:"peers_seen"`
	LastAnnounce    time.Time `json:"last_announce"`
	ErrorRate       float64   `json:"error_rate"`
}

// TrackerStats represents tracker-specific statistics
type TrackerStats struct {
	ActiveTorrents   int       `json:"active_torrents"`
	TotalPeers       int       `json:"total_peers"`
	AnnouncesPerMin  float64   `json:"announces_per_minute"`
	ScrapeRequests   int64     `json:"scrape_requests"`
	AverageSwarmSize float64   `json:"average_swarm_size"`
	LastActivity     time.Time `json:"last_activity"`
}

// GatewayStats represents gateway-specific statistics  
type GatewayStats struct {
	UploadsPerHour   float64 `json:"uploads_per_hour"`
	DownloadsPerHour float64 `json:"downloads_per_hour"`
	BandwidthUsed    int64   `json:"bandwidth_used_bytes"`
	ActiveUploads    int     `json:"active_uploads"`
	ActiveDownloads  int     `json:"active_downloads"`
	CacheHitRate     float64 `json:"cache_hit_rate"`
	AverageFileSize  int64   `json:"average_file_size"`
}

// WebSocketStats represents WebSocket tracker statistics
type WebSocketStats struct {
	ActiveConnections int     `json:"active_connections"`
	WebRTCPeers      int     `json:"webrtc_peers"`
	MessagesPerSec   float64 `json:"messages_per_second"`
	ConnectionErrors int64   `json:"connection_errors"`
	PeerExchanges    int64   `json:"peer_exchanges"`
	AverageLatency   float64 `json:"average_latency_ms"`
}

// SystemStats represents overall system performance
type SystemStats struct {
	CPUUsage     float64 `json:"cpu_usage_percent"`
	MemoryUsage  int64   `json:"memory_usage_bytes"`
	GoroutineCount int   `json:"goroutine_count"`
	ResponseTime float64 `json:"avg_response_time_ms"`
	RequestsPerSec float64 `json:"requests_per_second"`
}

// BandwidthStats represents bandwidth usage tracking
type BandwidthStats struct {
	TorrentHash      string    `json:"torrent_hash"`
	BytesServed      int64     `json:"bytes_served"`
	BytesFromPeers   int64     `json:"bytes_from_peers"`
	P2POffloadPercent float64  `json:"p2p_offload_percent"`
	PeerCount        int       `json:"peer_count"`
	Timestamp        time.Time `json:"timestamp"`
}

// TimeSeriesPoint represents a single point in time-series data
type TimeSeriesPoint struct {
	Timestamp time.Time `json:"timestamp"`
	Value     float64   `json:"value"`
	Component string    `json:"component"`
	Metric    string    `json:"metric"`
}

// StatsCollector manages collection and aggregation of statistics
type StatsCollector struct {
	mutex       sync.RWMutex
	dhtStats    *DHTStats
	trackerStats *TrackerStats
	gatewayStats *GatewayStats
	wsStats     *WebSocketStats
	systemStats *SystemStats
	bandwidthMap map[string]*BandwidthStats
	
	// Rate tracking
	requestCounts map[string]int64
	errorCounts   map[string]int64
	lastReset     time.Time
	
	// Performance tracking
	responseTimes map[string][]float64
	activeConns   int64
}

// NewStatsCollector creates a new statistics collector
func NewStatsCollector() *StatsCollector {
	return &StatsCollector{
		dhtStats:      &DHTStats{},
		trackerStats:  &TrackerStats{},
		gatewayStats:  &GatewayStats{},
		wsStats:       &WebSocketStats{},
		systemStats:   &SystemStats{},
		bandwidthMap:  make(map[string]*BandwidthStats),
		requestCounts: make(map[string]int64),
		errorCounts:   make(map[string]int64),
		responseTimes: make(map[string][]float64),
		lastReset:     time.Now(),
	}
}

// RecordRequest increments request count for a component
func (sc *StatsCollector) RecordRequest(component string) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.requestCounts[component]++
}

// RecordError increments error count for a component  
func (sc *StatsCollector) RecordError(component string) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.errorCounts[component]++
}

// RecordResponseTime records response time for a component
func (sc *StatsCollector) RecordResponseTime(component string, duration time.Duration) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	ms := float64(duration.Nanoseconds()) / 1e6
	if sc.responseTimes[component] == nil {
		sc.responseTimes[component] = make([]float64, 0, 100)
	}
	sc.responseTimes[component] = append(sc.responseTimes[component], ms)
	
	// Keep only last 100 measurements
	if len(sc.responseTimes[component]) > 100 {
		sc.responseTimes[component] = sc.responseTimes[component][1:]
	}
}

// RecordBandwidth records bandwidth usage for a torrent
func (sc *StatsCollector) RecordBandwidth(torrentHash string, bytesServed, bytesFromPeers int64, peerCount int) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	
	var p2pOffload float64
	if bytesServed > 0 {
		p2pOffload = float64(bytesFromPeers) / float64(bytesServed) * 100
	}
	
	sc.bandwidthMap[torrentHash] = &BandwidthStats{
		TorrentHash:       torrentHash,
		BytesServed:       bytesServed,
		BytesFromPeers:    bytesFromPeers,
		P2POffloadPercent: p2pOffload,
		PeerCount:         peerCount,
		Timestamp:         time.Now(),
	}
}

// GetAverageResponseTime calculates average response time for a component
func (sc *StatsCollector) GetAverageResponseTime(component string) float64 {
	sc.mutex.RLock()
	defer sc.mutex.RUnlock()
	
	times := sc.responseTimes[component]
	if len(times) == 0 {
		return 0
	}
	
	var sum float64
	for _, t := range times {
		sum += t
	}
	return sum / float64(len(times))
}

// GetRequestRate calculates requests per second for a component
func (sc *StatsCollector) GetRequestRate(component string) float64 {
	sc.mutex.RLock()
	defer sc.mutex.RUnlock()
	
	duration := time.Since(sc.lastReset).Seconds()
	if duration == 0 {
		return 0
	}
	return float64(sc.requestCounts[component]) / duration
}

// GetErrorRate calculates error rate percentage for a component
func (sc *StatsCollector) GetErrorRate(component string) float64 {
	sc.mutex.RLock()
	defer sc.mutex.RUnlock()
	
	requests := sc.requestCounts[component]
	if requests == 0 {
		return 0
	}
	return float64(sc.errorCounts[component]) / float64(requests) * 100
}

// ResetCounters resets rate-based counters (called periodically)
func (sc *StatsCollector) ResetCounters() {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	
	// Reset counters but keep running totals for rates
	sc.requestCounts = make(map[string]int64)
	sc.errorCounts = make(map[string]int64)
	sc.lastReset = time.Now()
}

// UpdateDHTStats updates DHT statistics
func (sc *StatsCollector) UpdateDHTStats(stats *DHTStats) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.dhtStats = stats
}

// UpdateTrackerStats updates tracker statistics
func (sc *StatsCollector) UpdateTrackerStats(stats *TrackerStats) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.trackerStats = stats
}

// UpdateGatewayStats updates gateway statistics
func (sc *StatsCollector) UpdateGatewayStats(stats *GatewayStats) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.gatewayStats = stats
}

// UpdateWebSocketStats updates WebSocket statistics
func (sc *StatsCollector) UpdateWebSocketStats(stats *WebSocketStats) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.wsStats = stats
}

// UpdateSystemStats updates system statistics
func (sc *StatsCollector) UpdateSystemStats(stats *SystemStats) {
	sc.mutex.Lock()
	defer sc.mutex.Unlock()
	sc.systemStats = stats
}

// GetSnapshot returns a complete snapshot of current statistics
func (sc *StatsCollector) GetSnapshot() map[string]interface{} {
	sc.mutex.RLock()
	defer sc.mutex.RUnlock()
	
	return map[string]interface{}{
		"timestamp": time.Now().Format(time.RFC3339),
		"dht":       sc.dhtStats,
		"tracker":   sc.trackerStats,
		"gateway":   sc.gatewayStats,
		"websocket": sc.wsStats,
		"system":    sc.systemStats,
		"bandwidth": sc.bandwidthMap,
	}
}