"""Tests for the cognitive bridge module."""

from unittest.mock import MagicMock, patch

import pytest
from cognitive import MemorySystem

from greymatter_core.cognitive_bridge import get_memory, ollama_embed, reset


@pytest.fixture(autouse=True)
def _clean_singleton():
    """Ensure each test starts with a fresh singleton."""
    reset()
    yield
    reset()


@patch("greymatter_core.cognitive_bridge.ollama_embed", side_effect=ConnectionError)
def test_get_memory_returns_memory_system(mock_embed):
    """get_memory() should return a MemorySystem instance."""
    mem = get_memory(db_path=":memory:")
    assert isinstance(mem, MemorySystem)


@patch("greymatter_core.cognitive_bridge.ollama_embed", side_effect=ConnectionError)
def test_singleton_behavior(mock_embed):
    """Two calls to get_memory() should return the same object."""
    first = get_memory(db_path=":memory:")
    second = get_memory(db_path=":memory:")
    assert first is second


@patch("greymatter_core.cognitive_bridge.ollama_embed", side_effect=ConnectionError)
def test_ollama_fallback(mock_embed):
    """When Ollama is unreachable, get_memory should still work (keyword-only)."""
    mem = get_memory(db_path=":memory:")
    assert isinstance(mem, MemorySystem)
    # Embedding store should not be initialized
    assert mem._embed_fn is None


@patch("httpx.post")
def test_ollama_embed_success(mock_post):
    """ollama_embed should return the embedding list from the response."""
    fake_embedding = [0.1, 0.2, 0.3]
    mock_response = MagicMock()
    mock_response.json.return_value = {"embedding": fake_embedding}
    mock_response.raise_for_status = MagicMock()
    mock_post.return_value = mock_response

    result = ollama_embed("hello world")

    assert result == fake_embedding
    mock_post.assert_called_once_with(
        "http://localhost:11434/api/embeddings",
        json={"model": "nomic-embed-text", "prompt": "hello world"},
        timeout=5,
    )


@patch("greymatter_core.cognitive_bridge.ollama_embed", side_effect=ConnectionError)
def test_reset_clears_singleton(mock_embed):
    """After reset(), the next get_memory() call should create a new instance."""
    first = get_memory(db_path=":memory:")
    reset()
    second = get_memory(db_path=":memory:")
    assert first is not second
