// Tests for metrics registry
use super::super::{
    register_counter, register_gauge, register_histogram,
    increment_counter, set_gauge, observe_histogram,
    get_counter_value, get_gauge_value,
};

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_counter_registration_and_increment() {
        // Register a counter metric
        let counter = register_counter(
            "test_counter_total",
            "Test counter for unit tests",
        );
        assert!(counter.is_ok(), "Failed to register counter");

        // Increment the counter
        increment_counter("test_counter_total", 1.0);
        increment_counter("test_counter_total", 2.0);
        increment_counter("test_counter_total", 3.0);

        // Verify counter value
        let value = get_counter_value("test_counter_total");
        assert!(value.is_some(), "Counter value should exist");
        assert_eq!(value.unwrap(), 6.0, "Counter should equal 6.0");
    }

    #[test]
    fn test_counter_with_labels() {
        // Register a counter with labels
        let counter = register_counter(
            "test_labeled_counter_total",
            "Test labeled counter",
        );
        assert!(counter.is_ok());

        // Increment with different label values
        increment_counter("test_labeled_counter_total", 1.0);
        increment_counter("test_labeled_counter_total", 2.0);

        let value = get_counter_value("test_labeled_counter_total");
        assert!(value.is_some());
        assert_eq!(value.unwrap(), 3.0);
    }

    #[test]
    fn test_gauge_set_and_get() {
        // Register a gauge metric
        let gauge = register_gauge(
            "test_gauge",
            "Test gauge for unit tests",
        );
        assert!(gauge.is_ok(), "Failed to register gauge");

        // Set gauge value
        set_gauge("test_gauge", 42.5);

        // Verify gauge value
        let value = get_gauge_value("test_gauge");
        assert!(value.is_some(), "Gauge value should exist");
        assert_eq!(value.unwrap(), 42.5, "Gauge should equal 42.5");
    }

    #[test]
    fn test_gauge_increment_decrement() {
        // Register a gauge
        let gauge = register_gauge(
            "test_gauge_inc_dec",
            "Test gauge increment/decrement",
        );
        assert!(gauge.is_ok());

        // Set initial value
        set_gauge("test_gauge_inc_dec", 100.0);

        // Increment
        set_gauge("test_gauge_inc_dec", 110.0);
        let value = get_gauge_value("test_gauge_inc_dec");
        assert_eq!(value.unwrap(), 110.0);

        // Decrement
        set_gauge("test_gauge_inc_dec", 90.0);
        let value = get_gauge_value("test_gauge_inc_dec");
        assert_eq!(value.unwrap(), 90.0);
    }

    #[test]
    fn test_histogram_observations() {
        // Register a histogram
        let histogram = register_histogram(
            "test_histogram_seconds",
            "Test histogram for latency measurements",
            vec![0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0],
        );
        assert!(histogram.is_ok(), "Failed to register histogram");

        // Record observations
        observe_histogram("test_histogram_seconds", 0.002);
        observe_histogram("test_histogram_seconds", 0.008);
        observe_histogram("test_histogram_seconds", 0.015);
        observe_histogram("test_histogram_seconds", 0.1);
        observe_histogram("test_histogram_seconds", 0.5);

        // Histogram doesn't expose direct value retrieval
        // We validate by ensuring no panic occurs
    }

    // Note: Summary tests removed - Summary type no longer available in prometheus 0.14+
    // Use Histogram with appropriate buckets for quantile approximations instead

    #[test]
    fn test_duplicate_registration() {
        // First registration should succeed
        let counter1 = register_counter(
            "test_duplicate_counter_total",
            "Test duplicate registration",
        );
        assert!(counter1.is_ok());

        // Duplicate registration should also succeed (idempotent)
        let counter2 = register_counter(
            "test_duplicate_counter_total",
            "Test duplicate registration",
        );
        assert!(counter2.is_ok());
    }

    #[test]
    fn test_metric_naming_convention() {
        // Test that metric names follow Prometheus conventions
        let valid_names = vec![
            "foxhunt_grpc_requests_total",
            "foxhunt_active_positions",
            "foxhunt_gpu_memory_bytes",
            "foxhunt_ml_training_duration_seconds",
        ];

        for name in valid_names {
            let counter = register_counter(name, "Test metric");
            assert!(counter.is_ok(), "Valid metric name should register: {}", name);
        }
    }

    #[test]
    fn test_concurrent_metric_updates() {
        use std::thread;

        // Register a counter for concurrent access
        let counter = register_counter(
            "test_concurrent_counter_total",
            "Test concurrent counter updates",
        );
        assert!(counter.is_ok());

        // Spawn multiple threads to increment concurrently
        let handles: Vec<_> = (0..10)
            .map(|_| {
                thread::spawn(|| {
                    for _ in 0..100 {
                        increment_counter("test_concurrent_counter_total", 1.0);
                    }
                })
            })
            .collect();

        // Wait for all threads
        for handle in handles {
            handle.join().unwrap();
        }

        // Verify final count (10 threads * 100 increments = 1000)
        let value = get_counter_value("test_concurrent_counter_total");
        assert!(value.is_some());
        assert_eq!(value.unwrap(), 1000.0);
    }

    #[test]
    fn test_histogram_bucket_boundaries() {
        // Test histogram with specific buckets
        let buckets = vec![0.001, 0.01, 0.1, 1.0, 10.0];
        let histogram = register_histogram(
            "test_bucket_histogram_seconds",
            "Test histogram bucket boundaries",
            buckets.clone(),
        );
        assert!(histogram.is_ok());

        // Observe values in different buckets
        observe_histogram("test_bucket_histogram_seconds", 0.0005);  // < 0.001
        observe_histogram("test_bucket_histogram_seconds", 0.005);   // 0.001-0.01
        observe_histogram("test_bucket_histogram_seconds", 0.05);    // 0.01-0.1
        observe_histogram("test_bucket_histogram_seconds", 0.5);     // 0.1-1.0
        observe_histogram("test_bucket_histogram_seconds", 5.0);     // 1.0-10.0
        observe_histogram("test_bucket_histogram_seconds", 15.0);    // > 10.0

    }
}
