"""
Coverage tests for BrowseCompQuestionGenerator.

Tests cover missing branches in:
- generate_questions: iteration==1 calls _extract_entities + _generate_initial_searches
- generate_questions: iteration>1 with existing entities calls _generate_progressive_searches
- _expand_temporal_ranges: year range "2018-2023" expanded to individual years
- _expand_temporal_ranges: entity with no year pattern kept as-is
- _generate_initial_searches: num_questions<=1 returns only original query
- _generate_initial_searches: temporal entities with <=10 items used
- _format_previous_searches: result_count known shows count; unknown shows "?"
- _was_searched: term present returns True; absent returns False
"""

from unittest.mock import MagicMock

from local_deep_research.advanced_search_system.questions.browsecomp_question import (
    BrowseCompQuestionGenerator,
)

MODULE = (
    "local_deep_research.advanced_search_system.questions.browsecomp_question"
)


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _make_generator(**kwargs):
    model = MagicMock()
    model.invoke.return_value = MagicMock(
        content="TEMPORAL: 2020\nNUMERICAL: 5\nNAMES: Dartmouth\nLOCATIONS: \nDESCRIPTORS: conference"
    )
    gen = BrowseCompQuestionGenerator(model, **kwargs)
    return gen, model


# ---------------------------------------------------------------------------
# generate_questions: iteration 1 path
# ---------------------------------------------------------------------------


class TestGenerateQuestionsFirstIteration:
    """Iteration 1 extracts entities and generates initial searches."""

    def test_iteration_one_calls_extract_entities(self):
        gen, model = _make_generator()
        # model response for entity extraction
        model.invoke.return_value = MagicMock(
            content="TEMPORAL: 2020\nNUMERICAL: \nNAMES: TestName\nLOCATIONS: \nDESCRIPTORS: "
        )

        questions = gen.generate_questions(
            current_knowledge="",
            query="Find something in 2020",
            questions_per_iteration=3,
            iteration=1,
        )

        # Entity extraction should have run
        assert (
            "TestName" in gen.extracted_entities.get("names", [])
            or len(questions) >= 1
        )

    def test_iteration_one_always_includes_original_query(self):
        gen, model = _make_generator()
        model.invoke.return_value = MagicMock(
            content="TEMPORAL: \nNUMERICAL: \nNAMES: \nLOCATIONS: \nDESCRIPTORS: "
        )

        questions = gen.generate_questions(
            current_knowledge="",
            query="My original query",
            questions_per_iteration=3,
            iteration=1,
        )

        assert "My original query" in questions

    def test_subsequent_iteration_with_no_entities_extracts_again(self):
        """If extracted_entities is empty on iteration>1, extraction runs again."""
        gen, model = _make_generator()
        gen.extracted_entities = {}  # empty triggers re-extraction

        model.invoke.return_value = MagicMock(
            content="TEMPORAL: \nNUMERICAL: \nNAMES: ReName\nLOCATIONS: \nDESCRIPTORS: "
        )

        questions = gen.generate_questions(
            current_knowledge="",
            query="Re-run query",
            questions_per_iteration=2,
            iteration=3,
        )
        # Should have called extract_entities (returning initial searches)
        assert len(questions) >= 1


# ---------------------------------------------------------------------------
# _expand_temporal_ranges
# ---------------------------------------------------------------------------


class TestExpandTemporalRanges:
    """_expand_temporal_ranges expands year ranges into individual years."""

    def test_range_with_dash_expands_to_individual_years(self):
        gen, _ = _make_generator()
        result = gen._expand_temporal_ranges(["2018-2020"])
        assert "2018" in result
        assert "2019" in result
        assert "2020" in result

    def test_single_year_kept_as_is(self):
        gen, _ = _make_generator()
        result = gen._expand_temporal_ranges(["2023"])
        assert "2023" in result

    def test_non_year_entity_kept(self):
        gen, _ = _make_generator()
        result = gen._expand_temporal_ranges(["last decade"])
        assert "last decade" in result

    def test_duplicates_removed(self):
        gen, _ = _make_generator()
        result = gen._expand_temporal_ranges(["2020", "2020"])
        assert result.count("2020") == 1

    def test_range_with_and_expands(self):
        gen, _ = _make_generator()
        result = gen._expand_temporal_ranges(["between 2019 and 2021"])
        assert "2019" in result
        assert "2020" in result
        assert "2021" in result


# ---------------------------------------------------------------------------
# _generate_initial_searches
# ---------------------------------------------------------------------------


class TestGenerateInitialSearches:
    """_generate_initial_searches edge cases."""

    def test_num_questions_one_returns_only_original(self):
        gen, _ = _make_generator()
        entities = {
            "names": ["Name1"],
            "temporal": ["2020"],
            "locations": [],
            "descriptors": ["key"],
            "numerical": [],
        }
        result = gen._generate_initial_searches("original query", entities, 1)
        assert result == ["original query"]

    def test_temporal_entries_added_for_small_range(self):
        gen, _ = _make_generator()
        entities = {
            "names": ["Alpha"],
            "temporal": ["2018", "2019", "2020"],
            "locations": [],
            "descriptors": [],
            "numerical": [],
        }
        result = gen._generate_initial_searches("find alpha", entities, 10)
        # Should include year-based searches like "Alpha 2018"
        year_searches = [
            s for s in result if any(y in s for y in ["2018", "2019", "2020"])
        ]
        assert len(year_searches) >= 1

    def test_large_temporal_range_skipped(self):
        """If more than 10 temporal entries, no year-based searches generated."""
        gen, _ = _make_generator()
        entities = {
            "names": ["Alpha"],
            "temporal": [str(y) for y in range(2000, 2015)],  # 15 entries
            "locations": [],
            "descriptors": [],
            "numerical": [],
        }
        result = gen._generate_initial_searches("find alpha", entities, 5)
        # Year searches should NOT appear
        [s for s in result if s != "find alpha" and "Alpha" not in s]
        assert "find alpha" in result


# ---------------------------------------------------------------------------
# _format_previous_searches
# ---------------------------------------------------------------------------


class TestFormatPreviousSearches:
    """_format_previous_searches with and without result counts."""

    def test_known_result_count_appears_in_output(self):
        gen, _ = _make_generator()
        questions = {1: ["search A", "search B"]}
        results = {1: 5}

        output = gen._format_previous_searches(questions, results)

        assert "5 results" in output
        assert "search A" in output

    def test_unknown_result_count_omitted(self):
        gen, _ = _make_generator()
        questions = {1: ["search X"]}
        results = {}  # No result for iteration 1 -> "?"

        output = gen._format_previous_searches(questions, results)

        assert "results" not in output
        assert "search X" in output

    def test_limit_applied_to_output(self):
        gen, _ = _make_generator(previous_searches_limit=2)
        questions = {i: [f"query{i}"] for i in range(10)}
        results = {}

        output = gen._format_previous_searches(questions, results)
        lines = [line for line in output.strip().split("\n") if line]
        assert len(lines) <= 2


# ---------------------------------------------------------------------------
# _was_searched
# ---------------------------------------------------------------------------


class TestWasSearched:
    """_was_searched checks if term appeared in prior questions."""

    def test_term_found_returns_true(self):
        gen, _ = _make_generator()
        questions = {1: ["dartmouth conference 2020"]}
        assert gen._was_searched("dartmouth", questions) is True

    def test_term_not_found_returns_false(self):
        gen, _ = _make_generator()
        questions = {1: ["something else"]}
        assert gen._was_searched("dartmouth", questions) is False

    def test_empty_dict_returns_false(self):
        gen, _ = _make_generator()
        assert gen._was_searched("anything", {}) is False

    def test_case_insensitive_match(self):
        gen, _ = _make_generator()
        questions = {1: ["DARTMOUTH Conference"]}
        assert gen._was_searched("dartmouth", questions) is True
