"""Direct tests for memory config parsing helpers."""
from __future__ import annotations

from pathlib import Path

import pytest

from logos_adk.errors import ConfigError
from logos_adk.memory import LongTermMemory, SessionMemory, SharedMemory
from logos_adk.memory.backends import (
    InMemoryBackend,
    PostgreSQLBackend,
    ShardedMemoryBackend,
    SQLiteBackend,
)
from logos_adk.memory.config import build_memory_backend, load_memories_from_config


def test_load_memories_from_config_supports_session_shorthand():
    memories = load_memories_from_config("session")

    assert len(memories) == 1
    assert isinstance(memories[0], SessionMemory)


def test_load_memories_from_config_builds_structured_memories(tmp_path):
    db_path = tmp_path / "memory.db"
    memories = load_memories_from_config(
        {
            "session": {"strategy": "summarize", "max_messages": 6},
            "long_term": {
                "backend": "sqlite",
                "path": str(db_path),
                "retrieval": "hybrid",
                "limit": 3,
                "learning": {"max_active_entries": 20, "max_context_limit": 7},
            },
            "shared": {
                "backend": "in_memory",
                "retrieval": "keyword",
                "limit": 4,
            },
        }
    )

    assert len(memories) == 3
    assert isinstance(memories[0], SessionMemory)
    assert memories[0].strategy == "summarize"
    assert memories[0].max_messages == 6
    assert isinstance(memories[1], LongTermMemory)
    assert isinstance(memories[1].backend, SQLiteBackend)
    assert Path(memories[1].backend.path) == db_path
    assert memories[1].retrieval == "hybrid"
    assert memories[1].limit == 3
    assert memories[1].learning is not None
    assert memories[1].learning.max_active_entries == 20
    assert memories[1].learning.max_context_limit == 7
    assert isinstance(memories[2], SharedMemory)
    assert isinstance(memories[2].backend, InMemoryBackend)
    assert memories[2].limit == 4


def test_load_memories_from_config_rejects_unknown_sections():
    with pytest.raises(ConfigError, match="Unknown memory config sections"):
        load_memories_from_config({"session": {}, "foo": {}})


def test_build_memory_backend_supports_known_backends(tmp_path):
    sqlite_backend = build_memory_backend({"backend": "sqlite", "path": str(tmp_path / "memory.db")})
    in_memory_backend = build_memory_backend({"backend": "in_memory"})
    postgres_backend = build_memory_backend(
        {"backend": "postgresql", "dsn": "postgresql://user:pass@localhost/db"}
    )
    sharded_backend = build_memory_backend(
        {
            "backend": "sharded",
            "shards": [
                {"backend": "sqlite", "path": str(tmp_path / "shard-a.db")},
                {"backend": "sqlite", "path": str(tmp_path / "shard-b.db")},
            ],
        }
    )

    assert isinstance(sqlite_backend, SQLiteBackend)
    assert isinstance(in_memory_backend, InMemoryBackend)
    assert isinstance(postgres_backend, PostgreSQLBackend)
    assert isinstance(sharded_backend, ShardedMemoryBackend)


def test_build_memory_backend_defaults_to_persistent_sqlite_and_rejects_unknown_backend():
    backend = build_memory_backend({})
    assert isinstance(backend, SQLiteBackend)
    assert backend.path.endswith("memory.db")

    with pytest.raises(ConfigError, match="Unsupported memory backend"):
        build_memory_backend({"backend": "redis"})


def test_build_memory_backend_prefers_postgres_when_database_url_is_set(monkeypatch):
    monkeypatch.setenv("DATABASE_URL", "postgresql://user:pass@localhost/prod")

    backend = build_memory_backend({})

    assert isinstance(backend, PostgreSQLBackend)
    assert backend.dsn == "postgresql://user:pass@localhost/prod"
