"""Test mem0 fact extraction calls provider with thinking disabled."""

import pytest
from unittest.mock import AsyncMock, MagicMock
from pathlib import Path

from nanobot.providers.base import LLMResponse


@pytest.fixture
def mock_provider():
    provider = AsyncMock()
    provider.chat = AsyncMock(return_value=LLMResponse(
        content='{"facts": ["user likes Python", "user works on nanobot"]}',
        finish_reason="end_turn",
    ))
    return provider


@pytest.fixture
def mem0_store(tmp_path):
    """Create a Mem0MemoryStore with mocked mem0 dependency."""
    # We can't import Mem0MemoryStore at module level because it requires
    # the mem0 package. Instead, we test extract_facts as a standalone method
    # by constructing a minimal instance.
    try:
        from nanobot.agent.memory_mem0 import Mem0MemoryStore
        store = Mem0MemoryStore(workspace=tmp_path)
        return store
    except ImportError:
        pytest.skip("mem0 not installed")


@pytest.mark.asyncio
async def test_extract_facts_passes_thinking_budget_zero(mock_provider):
    """extract_facts must pass thinking_budget=0 to provider.chat().

    Without this, the provider inherits its instance default (e.g. 10000),
    causing the model to spend tokens on thinking instead of outputting JSON.
    """
    try:
        from nanobot.agent.memory_mem0 import Mem0MemoryStore
    except ImportError:
        pytest.skip("mem0 not installed")

    # Create a minimal instance without full mem0 init
    store = object.__new__(Mem0MemoryStore)
    store.custom_prompt = "Extract facts as JSON: "

    messages = [
        {"role": "user", "content": "I like Python programming"},
        {"role": "assistant", "content": "That's great! Python is versatile."},
    ]

    facts = await store.extract_facts(messages, mock_provider, "claude-sonnet-4-5")

    # Verify provider.chat was called with thinking_budget=0
    mock_provider.chat.assert_called_once()
    call_kwargs = mock_provider.chat.call_args.kwargs
    assert call_kwargs["thinking_budget"] == 0


@pytest.mark.asyncio
async def test_extract_facts_returns_parsed_facts(mock_provider):
    """extract_facts should parse JSON response into a list of fact strings."""
    try:
        from nanobot.agent.memory_mem0 import Mem0MemoryStore
    except ImportError:
        pytest.skip("mem0 not installed")

    store = object.__new__(Mem0MemoryStore)
    store.custom_prompt = "Extract facts as JSON: "

    messages = [
        {"role": "user", "content": "I like Python programming"},
    ]

    facts = await store.extract_facts(messages, mock_provider, "claude-sonnet-4-5")

    assert facts == ["user likes Python", "user works on nanobot"]


@pytest.mark.asyncio
async def test_extract_facts_handles_empty_response():
    """extract_facts should return empty list when provider returns no content."""
    try:
        from nanobot.agent.memory_mem0 import Mem0MemoryStore
    except ImportError:
        pytest.skip("mem0 not installed")

    provider = AsyncMock()
    provider.chat = AsyncMock(return_value=LLMResponse(
        content="",
        finish_reason="end_turn",
    ))

    store = object.__new__(Mem0MemoryStore)
    store.custom_prompt = "Extract facts as JSON: "

    messages = [{"role": "user", "content": "Hello there"}]

    facts = await store.extract_facts(messages, provider, "claude-sonnet-4-5")

    assert facts == []


@pytest.mark.asyncio
async def test_extract_facts_skips_empty_messages():
    """extract_facts should return empty list when all messages have empty content."""
    try:
        from nanobot.agent.memory_mem0 import Mem0MemoryStore
    except ImportError:
        pytest.skip("mem0 not installed")

    provider = AsyncMock()

    store = object.__new__(Mem0MemoryStore)
    store.custom_prompt = "Extract facts as JSON: "

    messages = [
        {"role": "user", "content": ""},
        {"role": "assistant", "content": ""},
    ]

    facts = await store.extract_facts(messages, provider, "claude-sonnet-4-5")

    assert facts == []
    # Provider should not be called when there's no content
    provider.chat.assert_not_called()
