package intelligence

import (
	"context"
	"fmt"
	"runtime"
	"sort"
	"sync"
	"sync/atomic"
	"time"
)

// PerformanceMonitor provides comprehensive performance monitoring and benchmarking
type PerformanceMonitor struct {
	mu              sync.RWMutex
	config          *MonitorConfig
	metrics         *PerformanceMetrics
	benchmarks      map[string]*BenchmarkSuite
	profiler        *Profiler
	alertManager    *AlertManager
	reporters       []PerformanceReporter
	collectors      []MetricCollector
	isRunning       int32
	stopChan        chan struct{}
	collectInterval time.Duration
}

// MonitorConfig defines monitoring configuration
type MonitorConfig struct {
	EnableCPUProfiling    bool          `json:"enable_cpu_profiling"`
	EnableMemoryProfiling bool          `json:"enable_memory_profiling"`
	EnableGCStats         bool          `json:"enable_gc_stats"`
	CollectionInterval    time.Duration `json:"collection_interval"`
	RetentionPeriod       time.Duration `json:"retention_period"`
	AlertThresholds       *AlertThresholds `json:"alert_thresholds"`
	ReportingEnabled      bool          `json:"reporting_enabled"`
	BenchmarkingEnabled   bool          `json:"benchmarking_enabled"`
	MaxMetricHistory      int           `json:"max_metric_history"`
}

// AlertThresholds defines alert thresholds
type AlertThresholds struct {
	CPUUsagePercent       float64       `json:"cpu_usage_percent"`
	MemoryUsageMB         int64         `json:"memory_usage_mb"`
	AnalysisTimeMS        int64         `json:"analysis_time_ms"`
	ErrorRatePercent      float64       `json:"error_rate_percent"`
	QueueSizeLimit        int           `json:"queue_size_limit"`
	ResponseTimeMS        int64         `json:"response_time_ms"`
}

// PerformanceMetrics contains comprehensive performance metrics
type PerformanceMetrics struct {
	mu                    sync.RWMutex
	StartTime             time.Time                    `json:"start_time"`
	Uptime                time.Duration                `json:"uptime"`
	TotalOperations       int64                        `json:"total_operations"`
	SuccessfulOperations  int64                        `json:"successful_operations"`
	FailedOperations      int64                        `json:"failed_operations"`
	AverageResponseTime   time.Duration                `json:"average_response_time"`
	P95ResponseTime       time.Duration                `json:"p95_response_time"`
	P99ResponseTime       time.Duration                `json:"p99_response_time"`
	CPUUsage              float64                      `json:"cpu_usage"`
	MemoryUsage           *MemoryUsage                 `json:"memory_usage"`
	GCStats               *GCStats                     `json:"gc_stats"`
	ComponentMetrics      map[string]*ComponentMetrics `json:"component_metrics"`
	OperationMetrics      map[string]*OperationMetrics `json:"operation_metrics"`
	ResponseTimeHistory   []time.Duration              `json:"response_time_history"`
	LastUpdated           time.Time                    `json:"last_updated"`
}

// MemoryUsage contains memory usage statistics
type MemoryUsage struct {
	AllocBytes      uint64 `json:"alloc_bytes"`
	TotalAllocBytes uint64 `json:"total_alloc_bytes"`
	SysBytes        uint64 `json:"sys_bytes"`
	NumGC           uint32 `json:"num_gc"`
	HeapAllocBytes  uint64 `json:"heap_alloc_bytes"`
	HeapSysBytes    uint64 `json:"heap_sys_bytes"`
	StackInUse      uint64 `json:"stack_in_use"`
	StackSys        uint64 `json:"stack_sys"`
}

// GCStats contains garbage collection statistics
type GCStats struct {
	NumGC           uint32        `json:"num_gc"`
	PauseTotal      time.Duration `json:"pause_total"`
	PauseNs         []uint64      `json:"pause_ns"`
	LastGC          time.Time     `json:"last_gc"`
	NextGC          uint64        `json:"next_gc"`
	GCCPUFraction   float64       `json:"gc_cpu_fraction"`
}

// ComponentMetrics contains metrics for a specific component
type ComponentMetrics struct {
	ComponentName       string            `json:"component_name"`
	TotalCalls          int64             `json:"total_calls"`
	SuccessfulCalls     int64             `json:"successful_calls"`
	FailedCalls         int64             `json:"failed_calls"`
	AverageExecutionTime time.Duration    `json:"average_execution_time"`
	MinExecutionTime    time.Duration     `json:"min_execution_time"`
	MaxExecutionTime    time.Duration     `json:"max_execution_time"`
	ErrorRate           float64           `json:"error_rate"`
	LastExecutionTime   time.Time         `json:"last_execution_time"`
	CustomMetrics       map[string]interface{} `json:"custom_metrics"`
}

// OperationMetrics contains metrics for specific operations
type OperationMetrics struct {
	OperationName       string            `json:"operation_name"`
	TotalExecutions     int64             `json:"total_executions"`
	AverageLatency      time.Duration     `json:"average_latency"`
	P50Latency          time.Duration     `json:"p50_latency"`
	P95Latency          time.Duration     `json:"p95_latency"`
	P99Latency          time.Duration     `json:"p99_latency"`
	ThroughputPerSecond float64           `json:"throughput_per_second"`
	ErrorCount          int64             `json:"error_count"`
	LatencyHistory      []time.Duration   `json:"latency_history"`
	LastExecution       time.Time         `json:"last_execution"`
}

// BenchmarkSuite contains a suite of benchmarks
type BenchmarkSuite struct {
	SuiteName   string                 `json:"suite_name"`
	Benchmarks  map[string]*Benchmark  `json:"benchmarks"`
	Results     *BenchmarkResults      `json:"results"`
	Config      *BenchmarkConfig       `json:"config"`
	LastRun     time.Time              `json:"last_run"`
	IsRunning   bool                   `json:"is_running"`
}

// Benchmark defines a specific benchmark test
type Benchmark struct {
	Name          string                 `json:"name"`
	Description   string                 `json:"description"`
	TestFunction  func(b *BenchmarkContext) error `json:"-"`
	Setup         func() error          `json:"-"`
	Teardown      func() error          `json:"-"`
	Iterations    int                   `json:"iterations"`
	Duration      time.Duration         `json:"duration"`
	Parameters    map[string]interface{} `json:"parameters"`
	Tags          []string              `json:"tags"`
}

// BenchmarkContext provides context for benchmark execution
type BenchmarkContext struct {
	Name        string                 `json:"name"`
	Iteration   int                   `json:"iteration"`
	StartTime   time.Time             `json:"start_time"`
	Parameters  map[string]interface{} `json:"parameters"`
	Metrics     map[string]interface{} `json:"metrics"`
}

// BenchmarkConfig configures benchmark execution
type BenchmarkConfig struct {
	DefaultIterations int           `json:"default_iterations"`
	MaxDuration      time.Duration  `json:"max_duration"`
	WarmupIterations int           `json:"warmup_iterations"`
	Parallel         bool          `json:"parallel"`
	CPUProfiling     bool          `json:"cpu_profiling"`
	MemoryProfiling  bool          `json:"memory_profiling"`
}

// BenchmarkResults contains benchmark execution results
type BenchmarkResults struct {
	SuiteName         string                    `json:"suite_name"`
	TotalBenchmarks   int                       `json:"total_benchmarks"`
	PassedBenchmarks  int                       `json:"passed_benchmarks"`
	FailedBenchmarks  int                       `json:"failed_benchmarks"`
	TotalDuration     time.Duration             `json:"total_duration"`
	Results           map[string]*BenchmarkResult `json:"results"`
	Summary           *BenchmarkSummary         `json:"summary"`
	ExecutedAt        time.Time                 `json:"executed_at"`
}

// BenchmarkResult contains results for a single benchmark
type BenchmarkResult struct {
	Name                string            `json:"name"`
	Iterations          int               `json:"iterations"`
	TotalDuration       time.Duration     `json:"total_duration"`
	AverageLatency      time.Duration     `json:"average_latency"`
	MinLatency          time.Duration     `json:"min_latency"`
	MaxLatency          time.Duration     `json:"max_latency"`
	StandardDeviation   time.Duration     `json:"standard_deviation"`
	OperationsPerSecond float64           `json:"operations_per_second"`
	MemoryAllocated     int64             `json:"memory_allocated"`
	MemoryAllocations   int64             `json:"memory_allocations"`
	Success             bool              `json:"success"`
	ErrorMessage        string            `json:"error_message"`
	Percentiles         map[int]time.Duration `json:"percentiles"`
	CustomMetrics       map[string]interface{} `json:"custom_metrics"`
}

// BenchmarkSummary provides summary statistics
type BenchmarkSummary struct {
	FastestBenchmark    string        `json:"fastest_benchmark"`
	SlowestBenchmark    string        `json:"slowest_benchmark"`
	AverageLatency      time.Duration `json:"average_latency"`
	TotalOperations     int64         `json:"total_operations"`
	OverallThroughput   float64       `json:"overall_throughput"`
	PerformanceGrade    string        `json:"performance_grade"`
	Recommendations     []string      `json:"recommendations"`
}

// Profiler provides performance profiling capabilities
type Profiler struct {
	enabled       bool
	cpuProfile    *CPUProfile
	memoryProfile *MemoryProfile
	profiles      map[string]*Profile
	mu            sync.RWMutex
}

// Profile represents a performance profile
type Profile struct {
	Name      string                 `json:"name"`
	Type      string                 `json:"type"`
	StartTime time.Time              `json:"start_time"`
	EndTime   time.Time              `json:"end_time"`
	Duration  time.Duration          `json:"duration"`
	Data      map[string]interface{} `json:"data"`
	FilePath  string                 `json:"file_path"`
}

// CPUProfile contains CPU profiling data
type CPUProfile struct {
	StartTime      time.Time `json:"start_time"`
	EndTime        time.Time `json:"end_time"`
	SampleRate     int       `json:"sample_rate"`
	TotalSamples   int64     `json:"total_samples"`
	ProfileData    []byte    `json:"profile_data"`
	HotFunctions   []string  `json:"hot_functions"`
}

// MemoryProfile contains memory profiling data
type MemoryProfile struct {
	StartTime       time.Time              `json:"start_time"`
	EndTime         time.Time              `json:"end_time"`
	HeapProfile     []byte                 `json:"heap_profile"`
	AllocProfile    []byte                 `json:"alloc_profile"`
	TopAllocations  []string               `json:"top_allocations"`
	MemoryLeaks     []MemoryLeak           `json:"memory_leaks"`
}

// MemoryLeak represents a potential memory leak
type MemoryLeak struct {
	Function    string    `json:"function"`
	Size        int64     `json:"size"`
	Count       int64     `json:"count"`
	DetectedAt  time.Time `json:"detected_at"`
	Severity    string    `json:"severity"`
}

// AlertManager manages performance alerts
type AlertManager struct {
	mu          sync.RWMutex
	thresholds  *AlertThresholds
	alerts      []*Alert
	handlers    []AlertHandler
	enabled     bool
}

// Alert represents a performance alert
type Alert struct {
	ID          string                 `json:"id"`
	Level       string                 `json:"level"` // info, warning, critical
	Title       string                 `json:"title"`
	Description string                 `json:"description"`
	Metric      string                 `json:"metric"`
	Value       interface{}            `json:"value"`
	Threshold   interface{}            `json:"threshold"`
	CreatedAt   time.Time              `json:"created_at"`
	ResolvedAt  *time.Time             `json:"resolved_at,omitempty"`
	Context     map[string]interface{} `json:"context"`
}

// AlertHandler interface for handling alerts
type AlertHandler interface {
	HandleAlert(alert *Alert) error
	GetName() string
	IsEnabled() bool
}

// PerformanceReporter interface for reporting performance data
type PerformanceReporter interface {
	ReportMetrics(metrics *PerformanceMetrics) error
	ReportBenchmarks(results *BenchmarkResults) error
	GetName() string
	IsEnabled() bool
}

// MetricCollector interface for collecting custom metrics
type MetricCollector interface {
	CollectMetrics() (map[string]interface{}, error)
	GetName() string
	GetInterval() time.Duration
}

// NewPerformanceMonitor creates a new performance monitor
func NewPerformanceMonitor(config *MonitorConfig) *PerformanceMonitor {
	if config == nil {
		config = &MonitorConfig{
			EnableCPUProfiling:    true,
			EnableMemoryProfiling: true,
			EnableGCStats:         true,
			CollectionInterval:    time.Second,
			RetentionPeriod:       24 * time.Hour,
			ReportingEnabled:      true,
			BenchmarkingEnabled:   true,
			MaxMetricHistory:      1000,
			AlertThresholds: &AlertThresholds{
				CPUUsagePercent:  80.0,
				MemoryUsageMB:    500,
				AnalysisTimeMS:   5000,
				ErrorRatePercent: 5.0,
				QueueSizeLimit:   1000,
				ResponseTimeMS:   1000,
			},
		}
	}

	monitor := &PerformanceMonitor{
		config:          config,
		metrics:         NewPerformanceMetrics(),
		benchmarks:      make(map[string]*BenchmarkSuite),
		profiler:        NewProfiler(),
		alertManager:    NewAlertManager(config.AlertThresholds),
		reporters:       []PerformanceReporter{},
		collectors:      []MetricCollector{},
		stopChan:        make(chan struct{}),
		collectInterval: config.CollectionInterval,
	}

	// Initialize built-in collectors
	monitor.initializeCollectors()

	return monitor
}

// Start begins performance monitoring
func (pm *PerformanceMonitor) Start(ctx context.Context) error {
	if !atomic.CompareAndSwapInt32(&pm.isRunning, 0, 1) {
		return fmt.Errorf("performance monitor is already running")
	}

	pm.metrics.StartTime = time.Now()

	// Start metric collection goroutine
	go pm.collectMetrics(ctx)

	// Start alert monitoring if enabled
	if pm.config.AlertThresholds != nil {
		go pm.monitorAlerts(ctx)
	}

	return nil
}

// Stop stops performance monitoring
func (pm *PerformanceMonitor) Stop() error {
	if !atomic.CompareAndSwapInt32(&pm.isRunning, 1, 0) {
		return fmt.Errorf("performance monitor is not running")
	}

	close(pm.stopChan)
	return nil
}

// RecordOperation records metrics for an operation
func (pm *PerformanceMonitor) RecordOperation(operationName string, duration time.Duration, success bool) {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	atomic.AddInt64(&pm.metrics.TotalOperations, 1)
	if success {
		atomic.AddInt64(&pm.metrics.SuccessfulOperations, 1)
	} else {
		atomic.AddInt64(&pm.metrics.FailedOperations, 1)
	}

	// Update operation metrics
	if pm.metrics.OperationMetrics == nil {
		pm.metrics.OperationMetrics = make(map[string]*OperationMetrics)
	}

	opMetrics, exists := pm.metrics.OperationMetrics[operationName]
	if !exists {
		opMetrics = &OperationMetrics{
			OperationName:   operationName,
			LatencyHistory:  make([]time.Duration, 0),
		}
		pm.metrics.OperationMetrics[operationName] = opMetrics
	}

	opMetrics.TotalExecutions++
	opMetrics.LastExecution = time.Now()
	if !success {
		opMetrics.ErrorCount++
	}

	// Update latency metrics
	opMetrics.LatencyHistory = append(opMetrics.LatencyHistory, duration)
	if len(opMetrics.LatencyHistory) > 100 { // Keep last 100 samples
		opMetrics.LatencyHistory = opMetrics.LatencyHistory[1:]
	}

	// Calculate percentiles
	pm.updateLatencyPercentiles(opMetrics)

	// Update average response time
	pm.updateAverageResponseTime(duration)
}

// RecordComponentMetrics records metrics for a specific component
func (pm *PerformanceMonitor) RecordComponentMetrics(componentName string, executionTime time.Duration, success bool, customMetrics map[string]interface{}) {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	if pm.metrics.ComponentMetrics == nil {
		pm.metrics.ComponentMetrics = make(map[string]*ComponentMetrics)
	}

	compMetrics, exists := pm.metrics.ComponentMetrics[componentName]
	if !exists {
		compMetrics = &ComponentMetrics{
			ComponentName: componentName,
			MinExecutionTime: executionTime,
			MaxExecutionTime: executionTime,
			CustomMetrics: make(map[string]interface{}),
		}
		pm.metrics.ComponentMetrics[componentName] = compMetrics
	}

	compMetrics.TotalCalls++
	compMetrics.LastExecutionTime = time.Now()
	
	if success {
		compMetrics.SuccessfulCalls++
	} else {
		compMetrics.FailedCalls++
	}

	// Update execution time statistics
	totalTime := time.Duration(compMetrics.TotalCalls-1)*compMetrics.AverageExecutionTime + executionTime
	compMetrics.AverageExecutionTime = totalTime / time.Duration(compMetrics.TotalCalls)

	if executionTime < compMetrics.MinExecutionTime {
		compMetrics.MinExecutionTime = executionTime
	}
	if executionTime > compMetrics.MaxExecutionTime {
		compMetrics.MaxExecutionTime = executionTime
	}

	// Update error rate
	compMetrics.ErrorRate = float64(compMetrics.FailedCalls) / float64(compMetrics.TotalCalls)

	// Update custom metrics
	for key, value := range customMetrics {
		compMetrics.CustomMetrics[key] = value
	}
}

// GetMetrics returns current performance metrics
func (pm *PerformanceMonitor) GetMetrics() *PerformanceMetrics {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	// Create a deep copy to avoid race conditions
	metricsCopy := *pm.metrics
	metricsCopy.Uptime = time.Since(pm.metrics.StartTime)
	metricsCopy.LastUpdated = time.Now()

	return &metricsCopy
}

// RunBenchmark executes a benchmark suite
func (pm *PerformanceMonitor) RunBenchmark(ctx context.Context, suiteName string) (*BenchmarkResults, error) {
	if !pm.config.BenchmarkingEnabled {
		return nil, fmt.Errorf("benchmarking is disabled")
	}

	suite, exists := pm.benchmarks[suiteName]
	if !exists {
		return nil, fmt.Errorf("benchmark suite '%s' not found", suiteName)
	}

	suite.IsRunning = true
	defer func() { suite.IsRunning = false }()

	results := &BenchmarkResults{
		SuiteName:   suiteName,
		Results:     make(map[string]*BenchmarkResult),
		ExecutedAt:  time.Now(),
	}

	totalBenchmarks := len(suite.Benchmarks)
	results.TotalBenchmarks = totalBenchmarks

	startTime := time.Now()

	// Execute each benchmark
	for name, benchmark := range suite.Benchmarks {
		select {
		case <-ctx.Done():
			return nil, ctx.Err()
		default:
		}

		result, err := pm.executeBenchmark(ctx, benchmark)
		if err != nil {
			result = &BenchmarkResult{
				Name:         name,
				Success:      false,
				ErrorMessage: err.Error(),
			}
			results.FailedBenchmarks++
		} else {
			results.PassedBenchmarks++
		}

		results.Results[name] = result
	}

	results.TotalDuration = time.Since(startTime)
	results.Summary = pm.generateBenchmarkSummary(results)

	suite.Results = results
	suite.LastRun = time.Now()

	// Report results if reporters are configured
	pm.reportBenchmarkResults(results)

	return results, nil
}

// AddBenchmark adds a benchmark to a suite
func (pm *PerformanceMonitor) AddBenchmark(suiteName string, benchmark *Benchmark) {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	suite, exists := pm.benchmarks[suiteName]
	if !exists {
		suite = &BenchmarkSuite{
			SuiteName:  suiteName,
			Benchmarks: make(map[string]*Benchmark),
			Config: &BenchmarkConfig{
				DefaultIterations: 1000,
				MaxDuration:      time.Minute,
				WarmupIterations: 100,
				Parallel:         false,
			},
		}
		pm.benchmarks[suiteName] = suite
	}

	suite.Benchmarks[benchmark.Name] = benchmark
}

// StartProfiling begins performance profiling
func (pm *PerformanceMonitor) StartProfiling(profileType string) error {
	return pm.profiler.StartProfiling(profileType)
}

// StopProfiling stops performance profiling
func (pm *PerformanceMonitor) StopProfiling(profileType string) (*Profile, error) {
	return pm.profiler.StopProfiling(profileType)
}

// AddReporter adds a performance reporter
func (pm *PerformanceMonitor) AddReporter(reporter PerformanceReporter) {
	pm.mu.Lock()
	defer pm.mu.Unlock()
	pm.reporters = append(pm.reporters, reporter)
}

// AddCollector adds a metric collector
func (pm *PerformanceMonitor) AddCollector(collector MetricCollector) {
	pm.mu.Lock()
	defer pm.mu.Unlock()
	pm.collectors = append(pm.collectors, collector)
}

// GetAlerts returns current alerts
func (pm *PerformanceMonitor) GetAlerts() []*Alert {
	return pm.alertManager.GetAlerts()
}

// Private methods

func (pm *PerformanceMonitor) collectMetrics(ctx context.Context) {
	ticker := time.NewTicker(pm.collectInterval)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-pm.stopChan:
			return
		case <-ticker.C:
			pm.updateSystemMetrics()
			pm.collectCustomMetrics()
		}
	}
}

func (pm *PerformanceMonitor) updateSystemMetrics() {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	// Update memory usage
	var memStats runtime.MemStats
	runtime.ReadMemStats(&memStats)

	pm.metrics.MemoryUsage = &MemoryUsage{
		AllocBytes:      memStats.Alloc,
		TotalAllocBytes: memStats.TotalAlloc,
		SysBytes:        memStats.Sys,
		NumGC:           memStats.NumGC,
		HeapAllocBytes:  memStats.HeapAlloc,
		HeapSysBytes:    memStats.HeapSys,
		StackInUse:      memStats.StackInuse,
		StackSys:        memStats.StackSys,
	}

	// Update GC stats if enabled
	if pm.config.EnableGCStats {
		pm.metrics.GCStats = &GCStats{
			NumGC:         memStats.NumGC,
			PauseTotal:    time.Duration(memStats.PauseTotalNs),
			LastGC:        time.Unix(0, int64(memStats.LastGC)),
			NextGC:        memStats.NextGC,
			GCCPUFraction: memStats.GCCPUFraction,
		}
	}
}

func (pm *PerformanceMonitor) collectCustomMetrics() {
	for _, collector := range pm.collectors {
		if customMetrics, err := collector.CollectMetrics(); err == nil {
			// Store custom metrics in component metrics
			pm.RecordComponentMetrics(collector.GetName(), 0, true, customMetrics)
		}
	}
}

func (pm *PerformanceMonitor) updateLatencyPercentiles(opMetrics *OperationMetrics) {
	if len(opMetrics.LatencyHistory) == 0 {
		return
	}

	// Sort latencies for percentile calculation
	sorted := make([]time.Duration, len(opMetrics.LatencyHistory))
	copy(sorted, opMetrics.LatencyHistory)
	sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })

	// Calculate percentiles
	opMetrics.P50Latency = sorted[len(sorted)*50/100]
	opMetrics.P95Latency = sorted[len(sorted)*95/100]
	opMetrics.P99Latency = sorted[len(sorted)*99/100]

	// Calculate average latency
	total := time.Duration(0)
	for _, latency := range sorted {
		total += latency
	}
	opMetrics.AverageLatency = total / time.Duration(len(sorted))

	// Calculate throughput
	if opMetrics.AverageLatency > 0 {
		opMetrics.ThroughputPerSecond = float64(time.Second) / float64(opMetrics.AverageLatency)
	}
}

func (pm *PerformanceMonitor) updateAverageResponseTime(duration time.Duration) {
	// Add to response time history
	pm.metrics.ResponseTimeHistory = append(pm.metrics.ResponseTimeHistory, duration)
	if len(pm.metrics.ResponseTimeHistory) > pm.config.MaxMetricHistory {
		pm.metrics.ResponseTimeHistory = pm.metrics.ResponseTimeHistory[1:]
	}

	// Calculate percentiles from history
	if len(pm.metrics.ResponseTimeHistory) > 0 {
		sorted := make([]time.Duration, len(pm.metrics.ResponseTimeHistory))
		copy(sorted, pm.metrics.ResponseTimeHistory)
		sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })

		pm.metrics.P95ResponseTime = sorted[len(sorted)*95/100]
		pm.metrics.P99ResponseTime = sorted[len(sorted)*99/100]

		// Update average
		total := time.Duration(0)
		for _, latency := range sorted {
			total += latency
		}
		pm.metrics.AverageResponseTime = total / time.Duration(len(sorted))
	}
}

func (pm *PerformanceMonitor) executeBenchmark(ctx context.Context, benchmark *Benchmark) (*BenchmarkResult, error) {
	result := &BenchmarkResult{
		Name:        benchmark.Name,
		Iterations:  benchmark.Iterations,
		Percentiles: make(map[int]time.Duration),
	}

	if benchmark.Setup != nil {
		if err := benchmark.Setup(); err != nil {
			return nil, fmt.Errorf("benchmark setup failed: %w", err)
		}
	}

	if benchmark.Teardown != nil {
		defer func() {
			if err := benchmark.Teardown(); err != nil {
				fmt.Printf("Benchmark teardown failed: %v\n", err)
			}
		}()
	}

	latencies := make([]time.Duration, benchmark.Iterations)
	var memBefore runtime.MemStats
	runtime.ReadMemStats(&memBefore)

	startTime := time.Now()

	// Execute benchmark iterations
	for i := 0; i < benchmark.Iterations; i++ {
		select {
		case <-ctx.Done():
			return nil, ctx.Err()
		default:
		}

		benchCtx := &BenchmarkContext{
			Name:       benchmark.Name,
			Iteration:  i,
			StartTime:  time.Now(),
			Parameters: benchmark.Parameters,
			Metrics:    make(map[string]interface{}),
		}

		iterStart := time.Now()
		if err := benchmark.TestFunction(benchCtx); err != nil {
			return nil, fmt.Errorf("benchmark iteration %d failed: %w", i, err)
		}
		latencies[i] = time.Since(iterStart)
	}

	result.TotalDuration = time.Since(startTime)

	// Calculate statistics
	var memAfter runtime.MemStats
	runtime.ReadMemStats(&memAfter)
	
	result.MemoryAllocated = int64(memAfter.TotalAlloc - memBefore.TotalAlloc)
	result.MemoryAllocations = int64(memAfter.Mallocs - memBefore.Mallocs)

	// Calculate latency statistics
	sort.Slice(latencies, func(i, j int) bool { return latencies[i] < latencies[j] })
	
	result.MinLatency = latencies[0]
	result.MaxLatency = latencies[len(latencies)-1]
	
	// Calculate average
	total := time.Duration(0)
	for _, latency := range latencies {
		total += latency
	}
	result.AverageLatency = total / time.Duration(len(latencies))
	
	// Calculate operations per second
	if result.AverageLatency > 0 {
		result.OperationsPerSecond = float64(time.Second) / float64(result.AverageLatency)
	}

	// Calculate percentiles
	result.Percentiles[50] = latencies[len(latencies)*50/100]
	result.Percentiles[95] = latencies[len(latencies)*95/100]
	result.Percentiles[99] = latencies[len(latencies)*99/100]

	// Calculate standard deviation
	variance := float64(0)
	avgFloat := float64(result.AverageLatency)
	for _, latency := range latencies {
		diff := float64(latency) - avgFloat
		variance += diff * diff
	}
	variance /= float64(len(latencies))
	result.StandardDeviation = time.Duration(variance)

	result.Success = true
	return result, nil
}

func (pm *PerformanceMonitor) generateBenchmarkSummary(results *BenchmarkResults) *BenchmarkSummary {
	summary := &BenchmarkSummary{
		Recommendations: []string{},
	}

	if len(results.Results) == 0 {
		return summary
	}

	fastest := ""
	slowest := ""
	var fastestTime time.Duration = time.Hour // Large initial value
	var slowestTime time.Duration = 0
	totalOps := int64(0)
	totalLatency := time.Duration(0)

	for name, result := range results.Results {
		if !result.Success {
			continue
		}

		totalOps += int64(result.Iterations)
		totalLatency += result.TotalDuration

		if result.AverageLatency < fastestTime {
			fastestTime = result.AverageLatency
			fastest = name
		}

		if result.AverageLatency > slowestTime {
			slowestTime = result.AverageLatency
			slowest = name
		}
	}

	summary.FastestBenchmark = fastest
	summary.SlowestBenchmark = slowest
	summary.TotalOperations = totalOps

	if totalOps > 0 {
		summary.AverageLatency = totalLatency / time.Duration(totalOps)
		summary.OverallThroughput = float64(totalOps) / results.TotalDuration.Seconds()
	}

	// Generate performance grade and recommendations
	summary.PerformanceGrade = pm.calculatePerformanceGrade(results)
	summary.Recommendations = pm.generateRecommendations(results)

	return summary
}

func (pm *PerformanceMonitor) calculatePerformanceGrade(results *BenchmarkResults) string {
	successRate := float64(results.PassedBenchmarks) / float64(results.TotalBenchmarks)
	
	if successRate < 0.8 {
		return "F"
	} else if successRate < 0.9 {
		return "D"
	} else if successRate < 0.95 {
		return "C"
	} else if successRate < 0.98 {
		return "B"
	} else {
		return "A"
	}
}

func (pm *PerformanceMonitor) generateRecommendations(results *BenchmarkResults) []string {
	recommendations := []string{}

	if results.FailedBenchmarks > 0 {
		recommendations = append(recommendations, "Fix failing benchmarks to improve reliability")
	}

	for _, result := range results.Results {
		if result.AverageLatency > time.Millisecond*100 {
			recommendations = append(recommendations, 
				fmt.Sprintf("Optimize %s performance (avg: %v)", result.Name, result.AverageLatency))
		}
		
		if result.MemoryAllocated > 1024*1024 { // 1MB
			recommendations = append(recommendations,
				fmt.Sprintf("Reduce memory allocations in %s", result.Name))
		}
	}

	return recommendations
}

func (pm *PerformanceMonitor) monitorAlerts(ctx context.Context) {
	ticker := time.NewTicker(time.Second * 10) // Check every 10 seconds
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-pm.stopChan:
			return
		case <-ticker.C:
			pm.checkAlerts()
		}
	}
}

func (pm *PerformanceMonitor) checkAlerts() {
	metrics := pm.GetMetrics()
	thresholds := pm.config.AlertThresholds

	// Check memory usage
	if metrics.MemoryUsage != nil {
		memUsageMB := int64(metrics.MemoryUsage.AllocBytes / 1024 / 1024)
		if memUsageMB > thresholds.MemoryUsageMB {
			pm.alertManager.CreateAlert("critical", "High Memory Usage",
				fmt.Sprintf("Memory usage: %d MB exceeds threshold: %d MB", memUsageMB, thresholds.MemoryUsageMB),
				"memory_usage", memUsageMB, thresholds.MemoryUsageMB)
		}
	}

	// Check error rate
	if metrics.TotalOperations > 0 {
		errorRate := float64(metrics.FailedOperations) / float64(metrics.TotalOperations) * 100
		if errorRate > thresholds.ErrorRatePercent {
			pm.alertManager.CreateAlert("warning", "High Error Rate",
				fmt.Sprintf("Error rate: %.2f%% exceeds threshold: %.2f%%", errorRate, thresholds.ErrorRatePercent),
				"error_rate", errorRate, thresholds.ErrorRatePercent)
		}
	}

	// Check response time
	if metrics.AverageResponseTime.Milliseconds() > thresholds.ResponseTimeMS {
		pm.alertManager.CreateAlert("warning", "High Response Time",
			fmt.Sprintf("Average response time: %v exceeds threshold: %d ms", 
				metrics.AverageResponseTime, thresholds.ResponseTimeMS),
			"response_time", metrics.AverageResponseTime, thresholds.ResponseTimeMS)
	}
}

func (pm *PerformanceMonitor) reportBenchmarkResults(results *BenchmarkResults) {
	for _, reporter := range pm.reporters {
		if reporter.IsEnabled() {
			go func(r PerformanceReporter) {
				if err := r.ReportBenchmarks(results); err != nil {
					fmt.Printf("Failed to report benchmarks to %s: %v\n", r.GetName(), err)
				}
			}(reporter)
		}
	}
}

func (pm *PerformanceMonitor) initializeCollectors() {
	// Add built-in system metrics collector
	pm.collectors = append(pm.collectors, &SystemMetricsCollector{})
}

// Helper constructors and implementations

func NewPerformanceMetrics() *PerformanceMetrics {
	return &PerformanceMetrics{
		ComponentMetrics:    make(map[string]*ComponentMetrics),
		OperationMetrics:    make(map[string]*OperationMetrics),
		ResponseTimeHistory: make([]time.Duration, 0),
		StartTime:           time.Now(),
	}
}

func NewProfiler() *Profiler {
	return &Profiler{
		profiles: make(map[string]*Profile),
	}
}

func (p *Profiler) StartProfiling(profileType string) error {
	p.mu.Lock()
	defer p.mu.Unlock()

	profile := &Profile{
		Name:      profileType,
		Type:      profileType,
		StartTime: time.Now(),
		Data:      make(map[string]interface{}),
	}

	p.profiles[profileType] = profile
	p.enabled = true

	return nil
}

func (p *Profiler) StopProfiling(profileType string) (*Profile, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	profile, exists := p.profiles[profileType]
	if !exists {
		return nil, fmt.Errorf("profile not found: %s", profileType)
	}

	profile.EndTime = time.Now()
	profile.Duration = profile.EndTime.Sub(profile.StartTime)

	delete(p.profiles, profileType)

	return profile, nil
}

func NewAlertManager(thresholds *AlertThresholds) *AlertManager {
	return &AlertManager{
		thresholds: thresholds,
		alerts:     make([]*Alert, 0),
		handlers:   make([]AlertHandler, 0),
		enabled:    true,
	}
}

func (am *AlertManager) CreateAlert(level, title, description, metric string, value, threshold interface{}) {
	am.mu.Lock()
	defer am.mu.Unlock()

	alert := &Alert{
		ID:          fmt.Sprintf("alert_%d", time.Now().UnixNano()),
		Level:       level,
		Title:       title,
		Description: description,
		Metric:      metric,
		Value:       value,
		Threshold:   threshold,
		CreatedAt:   time.Now(),
		Context:     make(map[string]interface{}),
	}

	am.alerts = append(am.alerts, alert)

	// Notify handlers
	for _, handler := range am.handlers {
		if handler.IsEnabled() {
			go handler.HandleAlert(alert)
		}
	}
}

func (am *AlertManager) GetAlerts() []*Alert {
	am.mu.RLock()
	defer am.mu.RUnlock()

	alerts := make([]*Alert, len(am.alerts))
	copy(alerts, am.alerts)
	return alerts
}

// SystemMetricsCollector collects system-level metrics
type SystemMetricsCollector struct{}

func (smc *SystemMetricsCollector) CollectMetrics() (map[string]interface{}, error) {
	metrics := make(map[string]interface{})
	
	// Collect goroutine count
	metrics["goroutines"] = runtime.NumGoroutine()
	
	// Collect CPU count
	metrics["cpus"] = runtime.NumCPU()
	
	return metrics, nil
}

func (smc *SystemMetricsCollector) GetName() string {
	return "system_metrics"
}

func (smc *SystemMetricsCollector) GetInterval() time.Duration {
	return time.Second * 5
}