"""High-value pure logic tests for CrossEngineFilter."""

import copy
from unittest.mock import patch


from local_deep_research.advanced_search_system.filters.cross_engine_filter import (
    CrossEngineFilter,
)


def _make_filter(**overrides):
    """Create a CrossEngineFilter with __init__ bypassed."""
    with patch.object(
        CrossEngineFilter, "__init__", lambda self, *a, **kw: None
    ):
        filt = CrossEngineFilter.__new__(CrossEngineFilter)
    filt.model = overrides.get("model", None)
    filt.max_results = overrides.get("max_results", 100)
    filt.default_reorder = overrides.get("default_reorder", True)
    filt.default_reindex = overrides.get("default_reindex", True)
    return filt


def _make_results(count, *, prefix="Result"):
    """Build a list of result dicts with sequential indices."""
    return [
        {"title": f"{prefix} {i}", "snippet": f"Snippet {i}", "index": str(i)}
        for i in range(count)
    ]


# ---------------------------------------------------------------------------
# _prepare_and_return
# ---------------------------------------------------------------------------
class TestPrepareAndReturn:
    """Tests for _prepare_and_return reindexing logic."""

    def test_reindex_true_updates_indices_sequentially(self):
        filt = _make_filter()
        results = _make_results(3)
        returned = filt._prepare_and_return(
            results, reindex=True, start_index=0
        )
        assert [r["index"] for r in returned] == ["1", "2", "3"]

    def test_reindex_true_with_start_index_offset(self):
        filt = _make_filter()
        results = _make_results(3)
        returned = filt._prepare_and_return(
            results, reindex=True, start_index=5
        )
        assert [r["index"] for r in returned] == ["6", "7", "8"]

    def test_reindex_false_leaves_results_unchanged(self):
        filt = _make_filter()
        results = _make_results(3)
        original = copy.deepcopy(results)
        returned = filt._prepare_and_return(
            results, reindex=False, start_index=0
        )
        assert returned == original

    def test_reindex_false_ignores_start_index(self):
        filt = _make_filter()
        results = [{"title": "A", "index": "99"}]
        filt._prepare_and_return(results, reindex=False, start_index=42)
        assert results[0]["index"] == "99"

    def test_reindex_empty_list(self):
        filt = _make_filter()
        returned = filt._prepare_and_return([], reindex=True, start_index=0)
        assert returned == []

    def test_reindex_single_result(self):
        filt = _make_filter()
        results = [{"title": "Only", "index": "0"}]
        filt._prepare_and_return(results, reindex=True, start_index=0)
        assert results[0]["index"] == "1"

    def test_reindex_mutates_in_place(self):
        filt = _make_filter()
        results = _make_results(2)
        returned = filt._prepare_and_return(
            results, reindex=True, start_index=0
        )
        assert returned is results
        assert results[0]["index"] == "1"

    def test_reindex_indices_are_strings(self):
        filt = _make_filter()
        results = _make_results(2)
        filt._prepare_and_return(results, reindex=True, start_index=10)
        for res in results:
            assert isinstance(res["index"], str)


# ---------------------------------------------------------------------------
# filter_results – model is None (short-circuit path)
# ---------------------------------------------------------------------------
class TestFilterResultsModelNone:
    """Tests for the early-return path when model is None."""

    def test_returns_all_when_under_max(self):
        filt = _make_filter(model=None, max_results=100, default_reindex=False)
        results = _make_results(5)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 5

    def test_truncates_to_max_results(self):
        filt = _make_filter(model=None, max_results=3, default_reindex=False)
        results = _make_results(8)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 3
        assert filtered[0]["title"] == "Result 0"

    def test_empty_results(self):
        filt = _make_filter(model=None, max_results=10, default_reindex=False)
        filtered = filt.filter_results([], query="test")
        assert filtered == []

    def test_reindex_applied_via_default(self):
        filt = _make_filter(model=None, max_results=100, default_reindex=True)
        results = _make_results(3)
        filtered = filt.filter_results(results, query="test", start_index=0)
        assert [r["index"] for r in filtered] == ["1", "2", "3"]

    def test_reindex_override_false(self):
        filt = _make_filter(model=None, max_results=100, default_reindex=True)
        results = _make_results(3)
        original_indices = [r["index"] for r in copy.deepcopy(results)]
        filtered = filt.filter_results(results, query="test", reindex=False)
        assert [r["index"] for r in filtered] == original_indices

    def test_start_index_with_reindex(self):
        filt = _make_filter(model=None, max_results=100, default_reindex=True)
        results = _make_results(2)
        filtered = filt.filter_results(results, query="q", start_index=10)
        assert filtered[0]["index"] == "11"
        assert filtered[1]["index"] == "12"


# ---------------------------------------------------------------------------
# filter_results – results <= 10 (short-circuit path regardless of model)
# ---------------------------------------------------------------------------
class TestFilterResultsFewResults:
    """Tests for the early-return path when len(results) <= 10."""

    def test_exactly_10_results_takes_shortcut(self):
        filt = _make_filter(
            model="fake_model", max_results=100, default_reindex=False
        )
        results = _make_results(10)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 10

    def test_single_result_with_model(self):
        filt = _make_filter(
            model="fake_model", max_results=100, default_reindex=False
        )
        results = _make_results(1)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 1

    def test_10_results_truncated_by_max_results(self):
        filt = _make_filter(
            model="fake_model", max_results=5, default_reindex=False
        )
        results = _make_results(10)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 5

    def test_10_results_reindexed(self):
        filt = _make_filter(
            model="fake_model", max_results=100, default_reindex=True
        )
        results = _make_results(10)
        filtered = filt.filter_results(results, query="test", start_index=0)
        assert [r["index"] for r in filtered] == [str(i) for i in range(1, 11)]


# ---------------------------------------------------------------------------
# filter_results – default parameter resolution
# ---------------------------------------------------------------------------
class TestFilterResultsDefaults:
    """Tests verifying reorder/reindex default resolution from instance."""

    def test_reorder_defaults_to_instance_value(self):
        filt = _make_filter(
            model=None,
            max_results=100,
            default_reorder=False,
            default_reindex=False,
        )
        results = _make_results(3)
        # With model=None, reorder isn't used, but reindex should come from default
        filtered = filt.filter_results(results, query="test")
        # reindex=False by default, so indices stay original
        assert filtered[0]["index"] == "0"

    def test_reindex_explicit_overrides_default(self):
        filt = _make_filter(model=None, max_results=100, default_reindex=False)
        results = _make_results(3)
        filtered = filt.filter_results(results, query="test", reindex=True)
        assert filtered[0]["index"] == "1"

    def test_max_results_exactly_equals_length(self):
        filt = _make_filter(model=None, max_results=5, default_reindex=False)
        results = _make_results(5)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 5

    def test_max_results_one(self):
        filt = _make_filter(model=None, max_results=1, default_reindex=False)
        results = _make_results(7)
        filtered = filt.filter_results(results, query="test")
        assert len(filtered) == 1
        assert filtered[0]["title"] == "Result 0"
