"""Tests for statusline stdin parsing and context-pct.json persistence."""

import json
import time
from pathlib import Path
from unittest.mock import patch

from launcher.statusline.providers import (
    get_context_usage,
    parse_stdin_data,
    persist_context_pct,
)
from launcher.statusline.widgets import context_widget


class TestParseStdinData:
    """Tests for parsing Claude Code JSON from stdin."""

    def test_returns_empty_dict_when_tty(self) -> None:
        with patch("sys.stdin") as mock_stdin:
            mock_stdin.isatty.return_value = True
            assert parse_stdin_data() == {}

    def test_returns_empty_dict_when_empty(self) -> None:
        with patch("sys.stdin") as mock_stdin:
            mock_stdin.isatty.return_value = False
            mock_stdin.read.return_value = ""
            assert parse_stdin_data() == {}

    def test_parses_valid_json(self) -> None:
        data = {"context_window": {"used_percentage": 47}, "session_id": "abc"}
        with patch("sys.stdin") as mock_stdin:
            mock_stdin.isatty.return_value = False
            mock_stdin.read.return_value = json.dumps(data)
            result = parse_stdin_data()
        assert result["context_window"]["used_percentage"] == 47

    def test_returns_empty_dict_on_invalid_json(self) -> None:
        with patch("sys.stdin") as mock_stdin:
            mock_stdin.isatty.return_value = False
            mock_stdin.read.return_value = "not json"
            assert parse_stdin_data() == {}


class TestGetContextUsage:
    """Tests for extracting context percentage."""

    def test_extracts_percentage(self) -> None:
        data = {"context_window": {"used_percentage": 42}}
        assert get_context_usage(data) == 42

    def test_returns_none_when_missing(self) -> None:
        assert get_context_usage({}) is None
        assert get_context_usage({"context_window": {}}) is None

    def test_returns_none_when_null(self) -> None:
        assert get_context_usage({"context_window": {"used_percentage": None}}) is None


class TestPersistContextPct:
    """Tests for writing context-pct.json."""

    def test_writes_cache_file(self, tmp_path: Path) -> None:
        sf_home = tmp_path / ".tribunal"
        sf_home.mkdir()
        data = {
            "context_window": {"used_percentage": 55},
            "session_id": "claude-abc",
        }
        with patch.dict("os.environ", {"SF_SESSION_ID": "test-123", "SKILLFIELD_HOME": str(sf_home)}):
            persist_context_pct(data)

        cache_file = sf_home / "sessions" / "test-123" / "context-pct.json"
        assert cache_file.exists()
        cached = json.loads(cache_file.read_text())
        assert cached["pct"] == 55
        assert cached["session_id"] == "claude-abc"
        assert abs(cached["ts"] - time.time()) < 5

    def test_does_nothing_when_no_percentage(self, tmp_path: Path) -> None:
        sf_home = tmp_path / ".tribunal"
        sf_home.mkdir()
        with patch.dict("os.environ", {"SF_SESSION_ID": "test-123", "SKILLFIELD_HOME": str(sf_home)}):
            persist_context_pct({})

        cache_file = sf_home / "sessions" / "test-123" / "context-pct.json"
        assert not cache_file.exists()


class TestContextWidget:
    """Tests for the context statusline widget."""

    def test_returns_empty_when_none(self) -> None:
        assert context_widget(None) == ""

    def test_normal_percentage(self) -> None:
        assert context_widget(47) == "[ctx:47%]"

    def test_warning_at_80(self) -> None:
        result = context_widget(85)
        assert "85%" in result
        assert "!" in result

    def test_critical_at_90(self) -> None:
        result = context_widget(95)
        assert "95%" in result
        assert "!!" in result

    def test_normal_just_below_warning_boundary(self) -> None:
        # 79% is below the 80% warning threshold
        assert context_widget(79) == "[ctx:79%]"

    def test_warning_at_exact_boundary(self) -> None:
        # 80% is exactly at the warning threshold - should show single !
        result = context_widget(80)
        assert "[ctx:80% !]" == result

    def test_warning_just_below_critical_boundary(self) -> None:
        # 89% is below the 90% critical threshold - should show single !
        result = context_widget(89)
        assert "[ctx:89% !]" == result

    def test_critical_at_exact_boundary(self) -> None:
        # 90% is exactly at the critical threshold - should show !!
        result = context_widget(90)
        assert "[ctx:90% !!]" == result
