"""Tests for the telemetry pipeline."""

from __future__ import annotations

from pathlib import Path

from llmhosts.telemetry.emitter import TelemetryEmitter
from llmhosts.telemetry.events import RoutingEvent, TelemetryTier


class TestRoutingEvent:
    def test_from_request_hashes_query(self) -> None:
        event = RoutingEvent.from_request("hello world", TelemetryTier.LOCAL, "llama3", 100, 50, 20)
        assert event.query_hash != "hello world"
        assert len(event.query_hash) == 64  # SHA-256 hex

    def test_same_query_same_hash(self) -> None:
        e1 = RoutingEvent.from_request("same query", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        e2 = RoutingEvent.from_request("same query", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        assert e1.query_hash == e2.query_hash

    def test_different_queries_different_hashes(self) -> None:
        e1 = RoutingEvent.from_request("query A", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        e2 = RoutingEvent.from_request("query B", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        assert e1.query_hash != e2.query_hash

    def test_to_dict_shape(self) -> None:
        event = RoutingEvent.from_request("test", TelemetryTier.RULE_BASED, "gemma3", 50, 10, 5)
        d = event.to_dict()
        assert "query_hash" in d
        assert "query" not in d  # privacy: query text must NOT be in dict
        assert "tier_used" in d
        assert "timestamp" in d

    def test_tier_values(self) -> None:
        assert TelemetryTier.RULE_BASED.value == "rule_based"
        assert TelemetryTier.KNNCLASSIFIER.value == "knn"
        assert TelemetryTier.MODERNBERT.value == "modernbert"
        assert TelemetryTier.LOCAL.value == "local"

    def test_default_fields(self) -> None:
        event = RoutingEvent.from_request("q", TelemetryTier.LOCAL, "m", 1.0, 5, 3)
        assert event.node_id == ""
        assert event.privacy_level == "external"
        assert event.cache_hit is False
        assert event.timestamp  # non-empty

    def test_cache_hit_field(self) -> None:
        event = RoutingEvent.from_request("q", TelemetryTier.LOCAL, "m", 1.0, 5, 3, cache_hit=True)
        assert event.cache_hit is True

    def test_privacy_level_field(self) -> None:
        event = RoutingEvent.from_request("q", TelemetryTier.LOCAL, "m", 1.0, 5, 3, privacy_level="personal")
        assert event.privacy_level == "personal"


class TestTelemetryEmitter:
    def test_emit_and_retrieve(self, tmp_path: Path) -> None:
        db = tmp_path / "test_tel.db"
        emitter = TelemetryEmitter(db_path=db, enabled=True)
        event = RoutingEvent.from_request("test query", TelemetryTier.LOCAL, "llama3", 200, 50, 30)
        emitter.emit(event)
        events = emitter.recent_events(limit=10)
        assert len(events) == 1
        assert events[0]["model"] == "llama3"

    def test_status_counts(self, tmp_path: Path) -> None:
        db = tmp_path / "test_tel2.db"
        emitter = TelemetryEmitter(db_path=db, enabled=True)
        for i in range(5):
            event = RoutingEvent.from_request(f"query {i}", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
            emitter.emit(event)
        status = emitter.status()
        assert status["total_events"] == 5
        assert status["enabled"] is True

    def test_disabled_emitter_no_write(self, tmp_path: Path) -> None:
        db = tmp_path / "test_tel3.db"
        emitter = TelemetryEmitter(db_path=db, enabled=False)
        event = RoutingEvent.from_request("query", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        emitter.emit(event)  # should not write
        assert not db.exists()

    def test_emit_never_raises(self, tmp_path: Path) -> None:
        """Emitter must be silent even with a bad DB path."""
        emitter = TelemetryEmitter(db_path=Path("/nonexistent/path/tel.db"), enabled=True)
        # Should not raise
        event = RoutingEvent.from_request("x", TelemetryTier.LOCAL, "m", 1, 1, 1)
        emitter.emit(event)

    def test_privacy_no_query_text_in_db(self, tmp_path: Path) -> None:
        """Verify query text is never stored, only its hash."""
        db = tmp_path / "test_privacy.db"
        emitter = TelemetryEmitter(db_path=db, enabled=True)
        event = RoutingEvent.from_request("secret query text", TelemetryTier.LOCAL, "llama3", 100, 10, 5)
        emitter.emit(event)
        # Raw DB content must not contain the query text
        raw = db.read_bytes()
        assert b"secret query text" not in raw

    def test_status_disabled(self, tmp_path: Path) -> None:
        db = tmp_path / "disabled.db"
        emitter = TelemetryEmitter(db_path=db, enabled=False)
        status = emitter.status()
        assert status["enabled"] is False
        assert status["total_events"] == 0

    def test_recent_events_disabled(self, tmp_path: Path) -> None:
        db = tmp_path / "disabled2.db"
        emitter = TelemetryEmitter(db_path=db, enabled=False)
        assert emitter.recent_events() == []

    def test_multiple_tiers_stored(self, tmp_path: Path) -> None:
        db = tmp_path / "tiers.db"
        emitter = TelemetryEmitter(db_path=db, enabled=True)
        for tier in TelemetryTier:
            event = RoutingEvent.from_request("q", tier, "model", 10, 5, 5)
            emitter.emit(event)
        status = emitter.status()
        assert status["total_events"] == len(TelemetryTier)
        events = emitter.recent_events(limit=10)
        tiers_stored = {ev["tier_used"] for ev in events}
        assert "local" in tiers_stored
        assert "rule_based" in tiers_stored

    def test_db_path_in_status(self, tmp_path: Path) -> None:
        db = tmp_path / "path_check.db"
        emitter = TelemetryEmitter(db_path=db, enabled=True)
        status = emitter.status()
        assert str(db) in status.get("db_path", "")
