"""
Tests for insaits/metrics.py - Prometheus metrics collector
"""

import pytest
from insa_its.metrics import MetricsCollector


class TestMetricsCounter:
    def test_increment_default(self):
        m = MetricsCollector()
        m.increment("messages_total")
        assert m.get_counter("messages_total") == 1.0

    def test_increment_multiple(self):
        m = MetricsCollector()
        m.increment("messages_total")
        m.increment("messages_total")
        m.increment("messages_total")
        assert m.get_counter("messages_total") == 3.0

    def test_increment_custom_amount(self):
        m = MetricsCollector()
        m.increment("bytes_total", amount=1024)
        assert m.get_counter("bytes_total") == 1024.0

    def test_increment_with_labels(self):
        m = MetricsCollector()
        m.increment("anomalies_total", {"severity": "high"})
        m.increment("anomalies_total", {"severity": "low"})
        m.increment("anomalies_total", {"severity": "high"})
        assert m.get_counter("anomalies_total", {"severity": "high"}) == 2.0
        assert m.get_counter("anomalies_total", {"severity": "low"}) == 1.0

    def test_get_counter_nonexistent(self):
        m = MetricsCollector()
        assert m.get_counter("nonexistent") == 0.0


class TestMetricsGauge:
    def test_set_gauge(self):
        m = MetricsCollector()
        m.gauge("active_agents", 5)
        assert m.get_gauge_value("active_agents") == 5.0

    def test_gauge_overwrite(self):
        m = MetricsCollector()
        m.gauge("active_agents", 5)
        m.gauge("active_agents", 3)
        assert m.get_gauge_value("active_agents") == 3.0

    def test_gauge_with_labels(self):
        m = MetricsCollector()
        m.gauge("queue_depth", 10, {"agent": "a1"})
        m.gauge("queue_depth", 5, {"agent": "a2"})
        assert m.get_gauge_value("queue_depth", {"agent": "a1"}) == 10.0
        assert m.get_gauge_value("queue_depth", {"agent": "a2"}) == 5.0

    def test_get_gauge_nonexistent(self):
        m = MetricsCollector()
        assert m.get_gauge_value("nonexistent") == 0.0


class TestMetricsHistogram:
    def test_observe(self):
        m = MetricsCollector()
        m.observe("latency_ms", 42.5)
        m.observe("latency_ms", 100.0)
        m.observe("latency_ms", 5.0)
        # Verify via render (histograms don't have a direct getter)
        output = m.render_prometheus()
        assert "latency_ms_count" in output
        assert "latency_ms_sum" in output
        assert "latency_ms_bucket" in output


class TestRecordMessage:
    def test_clean_message(self):
        m = MetricsCollector()
        m.record_message(had_anomaly=False, severity="info", processing_ms=10.0)
        assert m.get_counter("insaits_messages_total") == 1.0
        assert m.get_counter("insaits_anomalies_total", {"severity": "info"}) == 0.0

    def test_anomalous_message(self):
        m = MetricsCollector()
        m.record_message(had_anomaly=True, severity="high", processing_ms=50.0)
        assert m.get_counter("insaits_messages_total") == 1.0
        assert m.get_counter("insaits_anomalies_total", {"severity": "high"}) == 1.0


class TestRenderPrometheus:
    def test_empty_render(self):
        m = MetricsCollector()
        assert m.render_prometheus() == ""

    def test_counter_format(self):
        m = MetricsCollector()
        m.increment("test_total")
        output = m.render_prometheus()
        assert "# TYPE test_total counter" in output
        assert "test_total 1.0" in output

    def test_gauge_format(self):
        m = MetricsCollector()
        m.gauge("test_gauge", 42)
        output = m.render_prometheus()
        assert "# TYPE test_gauge gauge" in output
        assert "test_gauge 42" in output

    def test_labeled_counter_format(self):
        m = MetricsCollector()
        m.increment("errors", {"type": "timeout"})
        output = m.render_prometheus()
        assert 'errors{type="timeout"} 1.0' in output

    def test_histogram_buckets(self):
        m = MetricsCollector()
        m.observe("latency", 42.5)
        output = m.render_prometheus()
        # Should have bucket lines
        assert 'le="50"' in output
        assert 'le="+Inf"' in output
        assert "latency_sum" in output
        assert "latency_count" in output


class TestMetricsReset:
    def test_reset(self):
        m = MetricsCollector()
        m.increment("test")
        m.gauge("test_g", 5)
        m.observe("test_h", 10)
        m.reset()
        assert m.get_counter("test") == 0.0
        assert m.get_gauge_value("test_g") == 0.0
        assert m.render_prometheus() == ""
