"""Unit tests for the summarization module.

Covers BaseSummarizer machinery (input cap, truncation, think-tag stripping,
error handling) and the FocusedSummarizer prompt via a concrete summarizer.
"""

from unittest.mock import Mock

from local_deep_research.advanced_search_system.summarization import (
    FocusedSummarizer,
)


def _fake_model(content: str) -> Mock:
    model = Mock()
    model.invoke.return_value = Mock(content=content)
    return model


class TestFocusedSummarizer:
    def test_returns_llm_output_when_under_limit(self):
        model = _fake_model("Short summary.")
        result = FocusedSummarizer(model, focus_query="q").summarize(
            "some long content here"
        )

        assert result == "Short summary."
        model.invoke.assert_called_once()

    def test_empty_content_skips_llm_call(self):
        model = _fake_model("never used")
        result = FocusedSummarizer(model, focus_query="q").summarize("")

        assert result == ""
        model.invoke.assert_not_called()

    def test_truncates_summary_above_max_chars(self):
        long_text = "X" * 500
        model = _fake_model(long_text)
        result = FocusedSummarizer(
            model, focus_query="q", max_chars=100
        ).summarize("input")

        assert len(result) == 103  # 100 chars + "..."
        assert result.endswith("...")

    def test_strips_think_tags_from_response(self):
        model = _fake_model(
            "<think>internal reasoning</think>Actual summary content."
        )
        result = FocusedSummarizer(model, focus_query="q").summarize("input")

        assert "internal reasoning" not in result
        assert "Actual summary content." in result

    def test_returns_empty_string_on_llm_exception(self):
        model = Mock()
        model.invoke.side_effect = RuntimeError("rate limited")

        result = FocusedSummarizer(model, focus_query="q").summarize(
            "some content"
        )

        assert result == ""

    def test_truncates_oversized_input_before_prompting(self):
        model = _fake_model("ok")
        oversize_input = "A" * 50000
        FocusedSummarizer(model, focus_query="q").summarize(oversize_input)

        prompt = model.invoke.call_args.args[0]
        # The base class caps input at INPUT_TRUNCATE_CHARS so the LLM call
        # stays bounded rather than carrying the entire 50k input.
        assert len(prompt) < 50000

    def test_focus_query_and_max_sentences_in_prompt(self):
        model = _fake_model("ok")
        FocusedSummarizer(
            model, focus_query="What about cost?", max_sentences=7
        ).summarize("hello")

        prompt = model.invoke.call_args.args[0]
        assert "7 sentence" in prompt
        assert "What about cost?" in prompt
