"""
Tests for news/utils/headline_generator.py

Tests cover:
- Headline generation with mocked LLM
- Fallback behavior when LLM fails
- Edge cases: empty findings, long queries
"""

from unittest.mock import patch, MagicMock


class TestGenerateHeadline:
    """Tests for the generate_headline function."""

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_successful_headline_generation(self, mock_get_llm):
        """Test that headline is generated when LLM succeeds."""
        from local_deep_research.news.utils.headline_generator import (
            generate_headline,
        )

        # Setup mock LLM
        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = "Major Tech Company Announces New Product"
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        result = generate_headline(
            query="technology news",
            findings="A major tech company announced a new smartphone today.",
        )

        assert result == "Major Tech Company Announces New Product"
        mock_llm.invoke.assert_called_once()

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_headline_strips_quotes(self, mock_get_llm):
        """Test that quotes are stripped from generated headline."""
        from local_deep_research.news.utils.headline_generator import (
            generate_headline,
        )

        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = '"Breaking News: Event Occurs"'
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        result = generate_headline(query="news", findings="Something happened")

        assert not result.startswith('"')
        assert not result.endswith('"')

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_empty_findings_returns_failure_message(self, mock_get_llm):
        """Test that empty findings returns failure message."""
        from local_deep_research.news.utils.headline_generator import (
            generate_headline,
        )

        # Mock LLM to prevent actual calls
        mock_llm = MagicMock()
        mock_get_llm.return_value = mock_llm

        result = generate_headline(query="test query", findings="")

        assert result == "[Headline generation failed]"
        # LLM invoke should not be called without findings
        mock_llm.invoke.assert_not_called()

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_llm_exception_returns_failure_message(self, mock_get_llm):
        """Test that LLM exception results in failure message."""
        from local_deep_research.news.utils.headline_generator import (
            generate_headline,
        )

        mock_get_llm.side_effect = Exception("LLM error")

        result = generate_headline(query="test", findings="Some findings")

        assert result == "[Headline generation failed]"

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_llm_empty_response_returns_failure(self, mock_get_llm):
        """Test that empty LLM response returns failure message."""
        from local_deep_research.news.utils.headline_generator import (
            generate_headline,
        )

        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = ""
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        result = generate_headline(query="test", findings="Some findings")

        assert result == "[Headline generation failed]"


class TestGenerateWithLLM:
    """Tests for the internal _generate_with_llm function."""

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_uses_low_temperature(self, mock_get_llm):
        """Test that LLM is called with low temperature for consistency."""
        from local_deep_research.news.utils.headline_generator import (
            _generate_with_llm,
        )

        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = "Test Headline"
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        _generate_with_llm("query", "findings", 100)

        mock_get_llm.assert_called_once_with(temperature=0.3)

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_prompt_includes_findings(self, mock_get_llm):
        """Test that prompt includes the findings content."""
        from local_deep_research.news.utils.headline_generator import (
            _generate_with_llm,
        )

        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = "Test Headline"
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        _generate_with_llm("query", "Important findings about topic", 100)

        # Check that invoke was called with prompt containing findings
        call_args = mock_llm.invoke.call_args
        prompt = call_args[0][0]
        assert "Important findings about topic" in prompt

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_no_findings_returns_none(self, mock_get_llm):
        """Test that missing findings returns None."""
        from local_deep_research.news.utils.headline_generator import (
            _generate_with_llm,
        )

        # Mock LLM to prevent actual calls
        mock_llm = MagicMock()
        mock_get_llm.return_value = mock_llm

        result = _generate_with_llm("query", "", 100)

        assert result is None
        # LLM invoke should not be called without findings
        mock_llm.invoke.assert_not_called()

    @patch("local_deep_research.config.llm_config.get_llm")
    def test_strips_punctuation_from_ends(self, mock_get_llm):
        """Test that punctuation is stripped from headline ends."""
        from local_deep_research.news.utils.headline_generator import (
            _generate_with_llm,
        )

        mock_llm = MagicMock()
        mock_response = MagicMock()
        mock_response.content = "...Headline With Punctuation!!?"
        mock_llm.invoke.return_value = mock_response
        mock_get_llm.return_value = mock_llm

        result = _generate_with_llm("query", "findings", 100)

        assert not result.startswith(".")
        assert not result.endswith("!")
        assert not result.endswith("?")
