"""Tests for token budget utilities."""

from __future__ import annotations

from presentations_ai._token_budget import (
    estimate_tokens,
    is_within_token_budget,
    truncate_to_token_budget,
)


class TestEstimateTokens:
    def test_empty_string(self) -> None:
        assert estimate_tokens("") == 0

    def test_short_string(self) -> None:
        # "hello" = 5 chars, 5/4 = 1.25 -> ceil = 2
        assert estimate_tokens("hello") == 2

    def test_exact_multiple(self) -> None:
        # 8 chars, 8/4 = 2.0 -> ceil = 2
        assert estimate_tokens("12345678") == 2

    def test_long_string(self) -> None:
        text = "a" * 1000
        assert estimate_tokens(text) == 250


class TestTruncateToTokenBudget:
    def test_short_text_unchanged(self) -> None:
        text = "Short text"
        assert truncate_to_token_budget(text) == text

    def test_long_text_truncated(self) -> None:
        text = "a" * 100_000
        result = truncate_to_token_budget(text)
        assert len(result) < len(text)
        assert result.endswith("[Output truncated to fit token budget]")

    def test_custom_max_tokens(self) -> None:
        text = "a" * 1000
        result = truncate_to_token_budget(text, max_tokens=100)
        # 100 * 4 * 0.9 = 360 chars max
        assert len(result) < 1000
        assert "[Output truncated" in result

    def test_exact_boundary_not_truncated(self) -> None:
        # Default: 25000 * 4 * 0.9 = 90000 chars
        text = "a" * 90_000
        assert truncate_to_token_budget(text) == text


class TestIsWithinTokenBudget:
    def test_short_text_within_budget(self) -> None:
        assert is_within_token_budget("hello") is True

    def test_long_text_exceeds_budget(self) -> None:
        text = "a" * 100_000
        assert is_within_token_budget(text) is False

    def test_boundary(self) -> None:
        assert is_within_token_budget("a" * 90_000) is True
        assert is_within_token_budget("a" * 90_001) is False
