// RLM Prometheus Metrics
// Follows existing VAPORA metrics pattern

use once_cell::sync::Lazy;
use prometheus::{HistogramVec, IntCounterVec, IntGaugeVec, Opts, Registry};

/// Global metrics registry for RLM
pub static REGISTRY: Lazy<Registry> = Lazy::new(Registry::new);

/// Total chunks created by strategy
pub static CHUNKS_TOTAL: Lazy<IntCounterVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_chunks_total",
        "Total chunks created by strategy",
    );
    let counter = IntCounterVec::new(opts, &["strategy"]).unwrap();
    REGISTRY.register(Box::new(counter.clone())).unwrap();
    counter
});

/// Query duration (hybrid search)
pub static QUERY_DURATION: Lazy<HistogramVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_query_duration_seconds",
        "RLM query duration in seconds",
    );
    let histogram = HistogramVec::new(
        prometheus::HistogramOpts::from(opts).buckets(vec![
            0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0,
        ]),
        &["query_type"],
    )
    .unwrap();
    REGISTRY.register(Box::new(histogram.clone())).unwrap();
    histogram
});

/// Dispatch duration (LLM calls)
pub static DISPATCH_DURATION: Lazy<HistogramVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_dispatch_duration_seconds",
        "RLM dispatch duration in seconds",
    );
    let histogram = HistogramVec::new(
        prometheus::HistogramOpts::from(opts)
            .buckets(vec![0.1, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0, 60.0]),
        &["provider"],
    )
    .unwrap();
    REGISTRY.register(Box::new(histogram.clone())).unwrap();
    histogram
});

/// Sandbox executions by tier
pub static SANDBOX_EXECUTIONS: Lazy<IntCounterVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_sandbox_executions_total",
        "Total sandbox executions by tier",
    );
    let counter = IntCounterVec::new(opts, &["tier", "result"]).unwrap();
    REGISTRY.register(Box::new(counter.clone())).unwrap();
    counter
});

/// Current sandbox pool size
pub static SANDBOX_POOL_SIZE: Lazy<IntGaugeVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_sandbox_pool_size",
        "Current sandbox pool size by tier",
    );
    let gauge = IntGaugeVec::new(opts, &["tier"]).unwrap();
    REGISTRY.register(Box::new(gauge.clone())).unwrap();
    gauge
});

/// BM25 index size (documents)
pub static BM25_INDEX_SIZE: Lazy<IntGaugeVec> = Lazy::new(|| {
    let opts = Opts::new("vapora_rlm_bm25_index_size", "BM25 index size in documents");
    let gauge = IntGaugeVec::new(opts, &["index_name"]).unwrap();
    REGISTRY.register(Box::new(gauge.clone())).unwrap();
    gauge
});

/// Storage operations
pub static STORAGE_OPERATIONS: Lazy<IntCounterVec> = Lazy::new(|| {
    let opts = Opts::new(
        "vapora_rlm_storage_operations_total",
        "Total storage operations by type",
    );
    let counter = IntCounterVec::new(opts, &["operation", "result"]).unwrap();
    REGISTRY.register(Box::new(counter.clone())).unwrap();
    counter
});

/// Initialize metrics (called at startup)
pub fn init_metrics() {
    Lazy::force(&CHUNKS_TOTAL);
    Lazy::force(&QUERY_DURATION);
    Lazy::force(&DISPATCH_DURATION);
    Lazy::force(&SANDBOX_EXECUTIONS);
    Lazy::force(&SANDBOX_POOL_SIZE);
    Lazy::force(&BM25_INDEX_SIZE);
    Lazy::force(&STORAGE_OPERATIONS);
}

/// Get metrics in Prometheus text format
pub fn metrics_text() -> String {
    use prometheus::Encoder;
    let encoder = prometheus::TextEncoder::new();
    let metric_families = REGISTRY.gather();
    let mut buffer = Vec::new();
    encoder.encode(&metric_families, &mut buffer).unwrap();
    String::from_utf8(buffer).unwrap()
}
