"""Tests for cortex.hippo.token_estimation module (Hippo W2-9)."""

from cortex.hippo.token_estimation import estimate_session_tokens, estimate_tokens


class TestEstimateTokens:
    """Basic estimate_tokens (re-exported from compaction)."""

    def test_estimate_tokens_basic(self):
        # 4 chars → 1 token
        assert estimate_tokens("abcd") == 1
        # 5 chars → ceil(5/4) = 2
        assert estimate_tokens("abcde") == 2
        # empty → 1 (min)
        assert estimate_tokens("") == 1
        # 8 chars → 2
        assert estimate_tokens("12345678") == 2
        # 100 chars → 25
        assert estimate_tokens("a" * 100) == 25


class TestEstimateSessionTokens:
    """Session-level token estimation mirroring TS afterTurn logic."""

    def test_estimate_session_tokens_string_content(self):
        msgs = [{"content": "Hello world!"}]  # 12 chars → ceil(12/4) = 3
        assert estimate_session_tokens(msgs) == 3

    def test_estimate_session_tokens_array_content(self):
        msgs = [
            {
                "content": [
                    {"type": "text", "text": "abcd"},  # 4 → 1
                    {"type": "text", "text": "abcdefgh"},  # 8 → 2
                ]
            }
        ]
        assert estimate_session_tokens(msgs) == 3

    def test_estimate_session_tokens_array_with_tool_use(self):
        msgs = [
            {
                "content": [
                    {"type": "text", "text": "abcd"},  # 4 → 1
                    {
                        "type": "tool_use",
                        "input": {"key": "val"},  # str repr ~15 chars → 4
                    },
                ]
            }
        ]
        result = estimate_session_tokens(msgs)
        # text block = 1, tool_use input str repr has some tokens
        assert result >= 2

    def test_estimate_session_tokens_command_output(self):
        msgs = [
            {"command": "ls -la", "output": "file1\nfile2"}
        ]
        # "ls -la\nfile1\nfile2" = 18 chars → ceil(18/4) = 5
        assert estimate_session_tokens(msgs) == 5

    def test_estimate_session_tokens_empty(self):
        assert estimate_session_tokens([]) == 0

    def test_estimate_session_tokens_mixed(self):
        msgs = [
            {"content": "Hello"},  # 5 chars → 2
            {"command": "echo hi", "output": "hi"},  # "echo hi\nhi" = 10 → 3
            {
                "content": [
                    {"type": "text", "text": "test"},  # 4 → 1
                ]
            },
        ]
        assert estimate_session_tokens(msgs) == 6

    def test_estimate_session_tokens_content_takes_priority(self):
        """Messages with 'content' should use content path, not command path."""
        msgs = [{"content": "abcd", "command": "ignored"}]
        # content path: 4 chars → 1
        assert estimate_session_tokens(msgs) == 1

    def test_estimate_session_tokens_none_command_output(self):
        """Non-string command/output should be treated as empty."""
        msgs = [{"command": None, "output": None}]
        # "\n" = 1 char → 1
        assert estimate_session_tokens(msgs) == 1

    def test_estimate_session_tokens_no_matching_keys(self):
        """Messages without content/command/output contribute 0."""
        msgs = [{"role": "system", "metadata": {}}]
        assert estimate_session_tokens(msgs) == 0
