from unittest.mock import MagicMock

from GramAddict.core.goap import NavigationKnowledge, ScreenType
from GramAddict.core.qdrant_memory import QdrantBase


def test_qdrant_semantic_overlap_prevention():
    """
    TDD Test: Ensures that get_tab_for_screen and get_requirements
    do not suffer from vector similarity overlap. They must use exact payload matching.
    """
    # 1. Setup real NavigationKnowledge but with a mocked DB connection
    knowledge = NavigationKnowledge("testuser")
    mock_db = MagicMock(spec=QdrantBase)
    mock_db.is_connected = True
    mock_db.collection_name = "test_nav_knowledge"
    mock_client = MagicMock()
    mock_db.client = mock_client
    knowledge._db = mock_db

    # 2. Simulate the bug: if the system used query_points (embedding search)
    # The client shouldn't receive a query_points call.
    # It SHOULD receive a scroll call with a FieldCondition.

    # Mock scroll to return an empty result (not found)
    mock_client.scroll.return_value = ([], None)

    # Execute
    result_action = knowledge.get_action_for_screen(ScreenType.OWN_PROFILE)

    # Assert it returns None when there is no exact match
    assert result_action is None

    # Verify scroll was called with correct filter, NOT query_points
    assert mock_client.scroll.called, "Must use client.scroll for exact matching, not query_points"
    assert not mock_client.query_points.called, "query_points should not be used due to semantic overlap risks"

    # Verify the scroll filter checks for "result_screen" == "OWN_PROFILE"
    call_args = mock_client.scroll.call_args[1]
    scroll_filter = call_args.get("scroll_filter")
    assert scroll_filter is not None
    assert scroll_filter.must[0].key == "result_screen"
    assert scroll_filter.must[0].match.value == "OWN_PROFILE"


def test_qdrant_semantic_overlap_prevention_requirements():
    """
    TDD Test: Ensures that get_requirements uses exact matching.
    """
    knowledge = NavigationKnowledge("testuser")
    mock_db = MagicMock(spec=QdrantBase)
    mock_db.is_connected = True
    mock_db.collection_name = "test_nav_knowledge"
    mock_client = MagicMock()
    mock_db.client = mock_client
    knowledge._db = mock_db

    mock_client.scroll.return_value = ([], None)

    requirements = knowledge.get_requirements("open profile")

    assert requirements == []

    assert mock_client.scroll.called
    assert not mock_client.query_points.called

    call_args = mock_client.scroll.call_args[1]
    scroll_filter = call_args.get("scroll_filter")
    assert scroll_filter.must[0].key == "goal"
    assert scroll_filter.must[0].match.value == "open profile"


def test_qdrant_semantic_overlap_prevention_path_memory():
    """
    TDD Test: Ensures that PathMemory.recall_path uses a strict query_filter
    on the `start_screen` payload field so it doesn't recall a path that is
    semantically related but for the wrong screen.
    """
    from GramAddict.core.goap import PathMemory

    memory = PathMemory("testuser")
    mock_db = MagicMock(spec=QdrantBase)
    mock_db.is_connected = True
    mock_db.collection_name = "test_path_memory"
    mock_client = MagicMock()
    mock_db.client = mock_client
    memory._db = mock_db

    mock_client.query_points.return_value = MagicMock(points=[])
    mock_db._get_embedding.return_value = [0.1] * 768

    # Execute
    path = memory.recall_path("like post", "EXPLORE_GRID")

    assert path is None
    assert mock_client.query_points.called

    call_args = mock_client.query_points.call_args[1]
    query_filter = call_args.get("query_filter")
    assert query_filter is not None
    assert query_filter.must[0].key == "start_screen"
    assert query_filter.must[0].match.value == "EXPLORE_GRID"
