"""Tests for context & token visualization (Track: context_token_viz_20260301)."""

from src import ai_client
from typing import Any

def test_add_bleed_derived_aliases() -> None:
 """_add_bleed_derived must inject 'estimated_prompt_tokens' alias."""
 d = {"current": 100, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["estimated_prompt_tokens"] == 100

def test_add_bleed_derived_headroom() -> None:
 """_add_bleed_derived must calculate 'headroom'."""
 d = {"current": 400, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["headroom"] == 600

def test_add_bleed_derived_would_trim_false() -> None:
 """_add_bleed_derived must set 'would_trim' to False when under limit."""
 d = {"current": 100, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["would_trim"] is False

def test_add_bleed_derived_would_trim_true() -> None:
 """_add_bleed_derived must set 'would_trim' to True when over limit."""
 d = {"current": 1100, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["would_trim"] is True

def test_add_bleed_derived_breakdown() -> None:
 """_add_bleed_derived must calculate breakdown of current usage."""
 d = {"current": 500, "limit": 1000}
 result = ai_client._add_bleed_derived(d, sys_tok=100, tool_tok=50)
 assert result["sys_tokens"] == 100
 assert result["tool_tokens"] == 50
 assert result["history_tokens"] == 350

def test_add_bleed_derived_history_clamped_to_zero() -> None:
 """history_tokens should not be negative."""
 d = {"current": 50, "limit": 1000}
 result = ai_client._add_bleed_derived(d, sys_tok=100, tool_tok=50)
 assert result["history_tokens"] == 0

def test_add_bleed_derived_headroom_clamped_to_zero() -> None:
 """headroom should not be negative."""
 d = {"current": 1500, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["headroom"] == 0

def test_app_token_stats_initialized_empty(app_instance: Any) -> None:
 """App._token_stats should start empty."""
 assert app_instance.controller._token_stats == {}

def test_app_last_stable_md_initialized_empty(app_instance: Any) -> None:
 """App._last_stable_md should start empty."""
 assert app_instance.controller._last_stable_md == ''

def test_app_has_render_token_budget_panel(app_instance: Any) -> None:
 """App must have render_token_budget_panel function in gui_2 module."""
 import src.gui_2 as gui_2
 assert hasattr(gui_2, 'render_token_budget_panel'), "gui_2 module must have render_token_budget_panel function"

def test_would_trim_boundary_exact() -> None:
 """Exact limit should trigger would_trim (cur >= lim)."""
 d = {"current": 1000, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["would_trim"] is True

def test_would_trim_just_below_threshold() -> None:
 """Limit - 1 should not trigger would_trim."""
 d = {"current": 999, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["would_trim"] is False

def test_would_trim_just_above_threshold() -> None:
 """Limit + 1 should trigger would_trim."""
 d = {"current": 1001, "limit": 1000}
 result = ai_client._add_bleed_derived(d)
 assert result["would_trim"] is True

def test_gemini_cache_fields_accessible() -> None:
 """_gemini_cache and related fields must be accessible for stats rendering."""
 assert hasattr(ai_client, "_gemini_cache")
 assert hasattr(ai_client, "_gemini_cache_created_at")
 assert hasattr(ai_client, "_GEMINI_CACHE_TTL")

def test_anthropic_history_lock_accessible() -> None:
 """_anthropic_history_lock must be accessible for cache hint rendering."""
 assert hasattr(ai_client, "_anthropic_history_lock")
 assert hasattr(ai_client, "_anthropic_history")