"""
Tests for heartbeat pruning safety (H-4, #1181).
"""

from __future__ import annotations

import pytest

from cortex.hippo.config import HippoConfig
from cortex.hippo.engine import HippoEngine


def _make_engine(prune_heartbeats: bool = True) -> HippoEngine:
    """Create a minimal HippoEngine for pruning tests (no DB needed)."""
    config = HippoConfig(
        enabled=True,
        db_path=":memory:",
        prune_heartbeats=prune_heartbeats,
    )
    engine = HippoEngine(config=config)
    return engine


class TestHeartbeatPruning:
    """Tests for _prune_heartbeat_ok_turns and related methods."""

    def test_genuine_heartbeat_pruned(self):
        """HEARTBEAT_OK with no tools → pruned."""
        engine = _make_engine()
        messages = [
            {"role": "user", "content": "heartbeat ping"},
            {"role": "assistant", "content": "HEARTBEAT_OK"},
            {"role": "user", "content": "real question"},
            {"role": "assistant", "content": "real answer"},
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        assert len(result) == 2
        assert result[0]["content"] == "real question"
        assert result[1]["content"] == "real answer"

    def test_tool_call_turn_survives(self):
        """Turn with tool calls not pruned even if 'heartbeat' in content."""
        engine = _make_engine()
        messages = [
            {"role": "user", "content": "heartbeat check"},
            {
                "role": "assistant",
                "content": "HEARTBEAT_OK",
                "tool_calls": [{"id": "tc_1", "function": {"name": "check"}}],
            },
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        # Both messages survive because of tool calls
        assert len(result) == 2

    def test_partial_match_not_pruned(self):
        """'heartbeat check' response (not exact HEARTBEAT_OK) not pruned."""
        engine = _make_engine()
        messages = [
            {"role": "user", "content": "heartbeat"},
            {"role": "assistant", "content": "heartbeat check passed"},
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        # Not pruned — assistant content is not exactly "HEARTBEAT_OK"
        assert len(result) == 2

    def test_metadata_flag_pruning(self):
        """metadata.heartbeat_ack=True → pruned regardless of content."""
        engine = _make_engine()
        messages = [
            {"role": "user", "content": "ping"},
            {
                "role": "assistant",
                "content": "I'm alive!",
                "metadata": {"heartbeat_ack": True},
            },
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        assert len(result) == 0

    def test_prune_disabled_by_config(self):
        """config.prune_heartbeats=False → nothing pruned."""
        engine = _make_engine(prune_heartbeats=False)
        messages = [
            {"role": "user", "content": "heartbeat"},
            {"role": "assistant", "content": "HEARTBEAT_OK"},
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        # Nothing pruned — kill switch is off
        assert len(result) == 2

    def test_mixed_turns(self):
        """Alternating heartbeat and real turns — only heartbeats pruned."""
        engine = _make_engine()
        messages = [
            {"role": "user", "content": "heartbeat"},
            {"role": "assistant", "content": "HEARTBEAT_OK"},
            {"role": "user", "content": "what is 2+2?"},
            {"role": "assistant", "content": "4"},
            {"role": "user", "content": "heartbeat"},
            {"role": "assistant", "content": "HEARTBEAT_OK", "metadata": {"heartbeat_ack": True}},
            {"role": "user", "content": "thanks"},
            {"role": "assistant", "content": "you're welcome"},
        ]
        result = engine._prune_heartbeat_ok_turns(messages)
        assert len(result) == 4
        assert result[0]["content"] == "what is 2+2?"
        assert result[1]["content"] == "4"
        assert result[2]["content"] == "thanks"
        assert result[3]["content"] == "you're welcome"
