package nginx_log

import (
	"context"
	"testing"
	"time"
)

// TestPerformanceMonitor tests the performance monitoring system
func TestPerformanceMonitor(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping performance monitor test in short mode")
	}

	t.Run("BasicFunctionality", func(t *testing.T) {
		// Create monitor with custom thresholds for testing
		thresholds := &Thresholds{
			ParseStreamOpsPerSec: 100.0,    // Low threshold for testing
			SIMDOpsPerSec:        1000.0,   // Low threshold for testing
			MemoryPoolOpsPerSec:  10000.0,  // Low threshold for testing
			RegexCacheOpsPerSec:  100000.0, // Low threshold for testing
			MaxMemoryUsageMB:     1000.0,   // High threshold for testing
			MaxResponseTimeMS:    5000.0,   // High threshold for testing
		}

		monitor := NewMonitor(thresholds)

		// Test metrics collection
		monitor.collectMetrics()
		metrics := monitor.GetCurrentMetrics()

		// Verify metrics are populated
		if metrics.ParseStreamRate == 0 {
			t.Error("ParseStream rate not measured")
		}

		if metrics.SIMDRate == 0 {
			t.Error("SIMD rate not measured")
		}

		if metrics.MemoryPoolRate == 0 {
			t.Error("Memory pool rate not measured")
		}

		if metrics.RegexCacheRate == 0 {
			t.Error("Regex cache rate not measured")
		}

		t.Logf("Performance Metrics:")
		t.Logf("  ParseStream: %.2f ops/sec", metrics.ParseStreamRate)
		t.Logf("  SIMD: %.2f ops/sec", metrics.SIMDRate)
		t.Logf("  Memory Pool: %.2f ops/sec", metrics.MemoryPoolRate)
		t.Logf("  Regex Cache: %.2f ops/sec", metrics.RegexCacheRate)
		t.Logf("  Cache Hit Rate: %.2f%%", metrics.CacheHitRate*100)
	})

	t.Run("AlertGeneration", func(t *testing.T) {
		// Create monitor with very high thresholds to trigger alerts
		thresholds := &Thresholds{
			ParseStreamOpsPerSec: 1000000.0,  // Unrealistically high
			SIMDOpsPerSec:        10000000.0, // Unrealistically high
			MemoryPoolOpsPerSec:  100000000.0, // Unrealistically high
			RegexCacheOpsPerSec:  1000000000.0, // Unrealistically high
			MaxMemoryUsageMB:     1.0,         // Very low to trigger alert
			MaxResponseTimeMS:    0.1,         // Very low to trigger alert
		}

		monitor := NewMonitor(thresholds)
		
		// Set up alert collection
		alertsReceived := make([]Alert, 0)
		monitor.SetAlertCallback(func(alert Alert) {
			alertsReceived = append(alertsReceived, alert)
		})

		// Collect metrics and check thresholds
		monitor.collectMetrics()
		monitor.checkThresholds()

		// Allow some time for alerts to be processed
		time.Sleep(100 * time.Millisecond)

		// Verify alerts were generated
		recentAlerts := monitor.GetRecentAlerts(time.Minute)
		if len(recentAlerts) == 0 {
			t.Error("Expected alerts to be generated with high thresholds")
		}

		t.Logf("Generated %d alerts:", len(recentAlerts))
		for _, alert := range recentAlerts {
			t.Logf("  [%s] %s: %.2f vs threshold %.2f",
				alert.Level, alert.Component, alert.CurrentValue, alert.ThresholdValue)
		}

		// Test health status
		health := monitor.GetHealthStatus()
		if health == "healthy" {
			t.Error("Expected unhealthy status with high thresholds")
		}
		t.Logf("Health status: %s", health)
	})

	t.Run("MetricsExport", func(t *testing.T) {
		monitor := NewMonitor(DefaultThresholds())
		monitor.collectMetrics()

		// Test JSON export
		jsonData, err := monitor.ExportMetrics()
		if err != nil {
			t.Fatalf("Failed to export metrics: %v", err)
		}

		if len(jsonData) == 0 {
			t.Error("Exported JSON is empty")
		}

		t.Logf("Exported JSON length: %d bytes", len(jsonData))

		// Test performance report generation
		report := GetReport(monitor)
		if len(report) == 0 {
			t.Error("Performance report is empty")
		}

		t.Logf("Performance Report:\n%s", report)
	})

	t.Run("ContinuousMonitoring", func(t *testing.T) {
		monitor := NewMonitor(DefaultThresholds())
		
		// Set up alert tracking
		alertCount := 0
		monitor.SetAlertCallback(func(alert Alert) {
			alertCount++
		})

		// Start monitoring for a short period
		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
		defer cancel()

		// Start monitoring with short interval
		go monitor.StartMonitoring(ctx, 500*time.Millisecond)

		// Wait for monitoring to run
		<-ctx.Done()

		// Stop monitoring
		monitor.StopMonitoring()

		// Verify some metrics were collected
		metrics := monitor.GetCurrentMetrics()
		if metrics.Timestamp.IsZero() {
			t.Error("No metrics were collected during monitoring")
		}

		t.Logf("Monitoring completed. Final metrics timestamp: %s", 
			metrics.Timestamp.Format(time.RFC3339))
	})
}

// TestThresholds tests the default thresholds configuration
func TestThresholds(t *testing.T) {
	thresholds := DefaultThresholds()

	// Verify default thresholds are reasonable
	if thresholds.ParseStreamOpsPerSec < 100.0 {
		t.Error("ParseStream threshold too low")
	}

	if thresholds.SIMDOpsPerSec < 1000.0 {
		t.Error("SIMD threshold too low")
	}

	if thresholds.MemoryPoolOpsPerSec < 10000.0 {
		t.Error("Memory pool threshold too low")
	}

	if thresholds.RegexCacheOpsPerSec < 100000.0 {
		t.Error("Regex cache threshold too low")
	}

	t.Logf("Default thresholds: ParseStream=%.0f, SIMD=%.0f, MemPool=%.0f, Cache=%.0f",
		thresholds.ParseStreamOpsPerSec, thresholds.SIMDOpsPerSec,
		thresholds.MemoryPoolOpsPerSec, thresholds.RegexCacheOpsPerSec)
}

// TestOptimizationMonitoringIntegration tests the complete monitoring integration
func TestOptimizationMonitoringIntegration(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping optimization monitoring integration test in short mode")
	}

	// Test the high-level monitoring function
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	monitor := StartMonitoring(ctx)

	// Wait for some monitoring cycles
	time.Sleep(1 * time.Second)

	// Check that monitoring is working
	metrics := monitor.GetCurrentMetrics()
	if metrics.Timestamp.IsZero() {
		t.Error("Monitoring did not collect metrics")
	}

	// Get performance report
	report := GetReport(monitor)
	if len(report) == 0 {
		t.Error("Performance report generation failed")
	}

	// Check health status
	health := monitor.GetHealthStatus()
	if health == "" {
		t.Error("Health status not determined")
	}

	t.Logf("Integration test completed successfully")
	t.Logf("Health: %s", health)
	t.Logf("Latest metrics: ParseStream=%.2f, SIMD=%.2f ops/sec",
		metrics.ParseStreamRate, metrics.SIMDRate)

	// Stop monitoring
	monitor.StopMonitoring()
}

// BenchmarkPerformanceMonitoring benchmarks the monitoring overhead
func BenchmarkPerformanceMonitoring(b *testing.B) {
	monitor := NewMonitor(DefaultThresholds())
	
	b.ResetTimer()
	
	for i := 0; i < b.N; i++ {
		monitor.collectMetrics()
		monitor.checkThresholds()
	}
}