from unittest.mock import MagicMock, PropertyMock, patch

import pytest

from GramAddict.core.swarm_protocol import SwarmProtocol


@pytest.fixture
def swarm():
    with patch("GramAddict.core.qdrant_memory.QdrantClient"):
        return SwarmProtocol(username="test_bot")


def test_emit_pheromone(swarm):
    """Verify that emitting a pheromone calls Qdrant upsert with correct payload."""
    with patch("GramAddict.core.qdrant_memory.QdrantBase.is_connected", new_callable=PropertyMock, return_value=True):
        path_hash = "some_ui_path_hash"
        outcome = "success"

        swarm.emit_pheromone(path_hash, outcome)

        # Check if upsert was called with the expected payload
        swarm.client.upsert.assert_called_once()
        args, kwargs = swarm.client.upsert.call_args
        points = kwargs.get("points")
        assert points[0].payload["path_hash"] == path_hash
        assert points[0].payload["outcome"] == outcome
        assert points[0].payload["username"] == "test_bot"


def test_query_consensus_hit(swarm):
    """Verify consensus query returns the outcome from Qdrant scroll."""
    with patch("GramAddict.core.qdrant_memory.QdrantBase.is_connected", new_callable=PropertyMock, return_value=True):
        path_hash = "known_path"

        # Mock scroll result
        mock_point = MagicMock()
        mock_point.payload = {"outcome": "banned"}
        swarm.client.scroll.return_value = ([mock_point], None)

        result = swarm.query_consensus(path_hash)
        assert result == "banned"
        swarm.client.scroll.assert_called_once()


def test_query_consensus_miss(swarm):
    """Verify None is returned when no pheromones found."""
    with patch("GramAddict.core.qdrant_memory.QdrantBase.is_connected", new_callable=PropertyMock, return_value=True):
        swarm.client.scroll.return_value = ([], None)

        result = swarm.query_consensus("unknown_path")
        assert result is None


def test_offline_mode(swarm):
    """Protocol should not crash if Qdrant is disconnected."""
    with patch("GramAddict.core.qdrant_memory.QdrantBase.is_connected", new_callable=PropertyMock, return_value=False):
        swarm.emit_pheromone("any", "thing")
        swarm.client.upsert.assert_not_called()

        assert swarm.query_consensus("any") is None
