"""
Testes do sistema de memória
"""
import pytest
import asyncio
import os
from datetime import datetime

from core.memory import ConversationMemory, MemoryConfig


@pytest.fixture
async def memory():
    """Fixture para memória"""
    config = MemoryConfig(
        max_history=5,
        summary_threshold=20,
        storage_type="sqlite"
    )
    mem = ConversationMemory(config)
    yield mem
    # Cleanup
    if os.path.exists(mem.db_path):
        os.remove(mem.db_path)


class TestConversationMemory:
    """Testes de memória"""

    @pytest.mark.asyncio
    async def test_add_message(self, memory):
        """Testa adicionar mensagem"""
        await memory.add_message("session_1", "user", "Olá")
        history = await memory.get_history("session_1")

        assert len(history) == 1
        assert history[0]["role"] == "user"
        assert history[0]["content"] == "Olá"

    @pytest.mark.asyncio
    async def test_get_history_limit(self, memory):
        """Testa limite de histórico"""
        for i in range(10):
            await memory.add_message("session_2", "user", f"Mensagem {i}")

        history = await memory.get_history("session_2", limit=3)
        assert len(history) == 3

    @pytest.mark.asyncio
    async def test_multiple_sessions(self, memory):
        """Testa múltiplas sessões"""
        await memory.add_message("session_a", "user", "Sessão A")
        await memory.add_message("session_b", "user", "Sessão B")

        history_a = await memory.get_history("session_a")
        history_b = await memory.get_history("session_b")

        assert history_a[0]["content"] == "Sessão A"
        assert history_b[0]["content"] == "Sessão B"

    @pytest.mark.asyncio
    async def test_clear_history(self, memory):
        """Testa limpar histórico"""
        await memory.add_message("session_3", "user", "Teste")
        await memory.clear_history("session_3")

        history = await memory.get_history("session_3")
        assert len(history) == 0

    @pytest.mark.asyncio
    async def test_persistence(self, memory):
        """Testa persistência"""
        await memory.add_message("session_4", "user", "Persistente")

        # Criar nova instância (simula reinício)
        config = MemoryConfig()
        new_memory = ConversationMemory(config)

        history = await new_memory.get_history("session_4")
        assert len(history) == 1
        assert history[0]["content"] == "Persistente"

        # Cleanup
        if os.path.exists(new_memory.db_path):
            os.remove(new_memory.db_path)

    @pytest.mark.asyncio
    async def test_metadata(self, memory):
        """Testa metadados"""
        await memory.add_message(
            "session_5",
            "user",
            "Com metadata",
            metadata={"fonte": "teste", "importante": True}
        )

        history = await memory.get_history("session_5")
        # Metadata não é exposto diretamente no get_history,
        # mas é armazenado no banco

    @pytest.mark.asyncio
    async def test_concurrent_access(self, memory):
        """Testa acesso concorrente"""
        async def add_messages(session_id, count):
            for i in range(count):
                await memory.add_message(session_id, "user", f"Msg {i}")

        # Adicionar mensagens concorrentemente
        await asyncio.gather(
            add_messages("concurrent_1", 5),
            add_messages("concurrent_2", 5)
        )

        history_1 = await memory.get_history("concurrent_1")
        history_2 = await memory.get_history("concurrent_2")

        assert len(history_1) == 5
        assert len(history_2) == 5