"""Tests for RAG YAML config parsing."""
import pytest

from logos_adk.errors import ConfigError
from logos_adk.rag.config import load_knowledge_from_config
from logos_adk.rag.knowledge_base import KnowledgeBase
from logos_adk.rag.vector_postgresql import PostgreSQLVectorStore
from logos_adk.rag.vector_store import InMemoryVectorStore
from logos_adk.rag.vector_sqlite import SQLiteVectorStore


async def _fake_embed(text: str) -> list[float]:
    return [float(len(text)), 1.0]


class TestLoadKnowledgeFromConfig:
    def test_none_returns_none(self):
        assert load_knowledge_from_config(None) is None

    def test_non_dict_raises(self):
        with pytest.raises(ConfigError, match="must be a mapping"):
            load_knowledge_from_config("bad")

    def test_memory_backend(self):
        result = load_knowledge_from_config(
            {"backend": "memory"}, embed_fn=_fake_embed
        )
        assert result is not None
        assert isinstance(result["knowledge_base"], KnowledgeBase)
        assert isinstance(result["knowledge_base"].store, InMemoryVectorStore)
        assert result["mode"] == "memory"
        assert result["limit"] == 5

    def test_sqlite_backend(self, tmp_path):
        result = load_knowledge_from_config(
            {"backend": "sqlite", "path": str(tmp_path / "vec.db")},
            embed_fn=_fake_embed,
        )
        assert isinstance(result["knowledge_base"].store, SQLiteVectorStore)

    def test_sqlite_missing_path(self):
        with pytest.raises(ConfigError, match="requires 'path'"):
            load_knowledge_from_config(
                {"backend": "sqlite"}, embed_fn=_fake_embed
            )

    def test_postgresql_backend(self):
        result = load_knowledge_from_config(
            {"backend": "postgresql", "dsn": "postgresql://user:pass@localhost/rag"},
            embed_fn=_fake_embed,
        )
        assert isinstance(result["knowledge_base"].store, PostgreSQLVectorStore)

    def test_postgres_alias_backend(self):
        result = load_knowledge_from_config(
            {"backend": "postgres", "dsn": "postgresql://user:pass@localhost/rag"},
            embed_fn=_fake_embed,
        )
        assert isinstance(result["knowledge_base"].store, PostgreSQLVectorStore)

    def test_postgresql_missing_dsn(self, monkeypatch):
        monkeypatch.delenv("DATABASE_URL", raising=False)
        monkeypatch.delenv("LOGOS_ADK_DATABASE_URL", raising=False)
        with pytest.raises(ConfigError, match="requires a DSN"):
            load_knowledge_from_config(
                {"backend": "postgresql"}, embed_fn=_fake_embed
            )

    def test_unknown_backend(self):
        with pytest.raises(ConfigError, match="Unknown knowledge backend"):
            load_knowledge_from_config(
                {"backend": "faiss"}, embed_fn=_fake_embed
            )

    def test_custom_mode(self):
        result = load_knowledge_from_config(
            {"backend": "memory", "mode": "tool"}, embed_fn=_fake_embed
        )
        assert result["mode"] == "tool"

    def test_invalid_mode(self):
        with pytest.raises(ConfigError, match="Unknown knowledge mode"):
            load_knowledge_from_config(
                {"backend": "memory", "mode": "invalid"}, embed_fn=_fake_embed
            )

    def test_custom_limit(self):
        result = load_knowledge_from_config(
            {"backend": "memory", "limit": 10}, embed_fn=_fake_embed
        )
        assert result["limit"] == 10

    def test_invalid_limit(self):
        with pytest.raises(ConfigError, match="positive integer"):
            load_knowledge_from_config(
                {"backend": "memory", "limit": -1}, embed_fn=_fake_embed
            )

    def test_missing_embed_fn(self):
        with pytest.raises(ConfigError, match="embed_fn"):
            load_knowledge_from_config({"backend": "memory"})

    def test_splitter_config(self):
        result = load_knowledge_from_config(
            {
                "backend": "memory",
                "splitter": {"chunk_size": 500, "chunk_overlap": 50},
            },
            embed_fn=_fake_embed,
        )
        kb = result["knowledge_base"]
        assert kb.splitter.chunk_size == 500
        assert kb.splitter.chunk_overlap == 50

    def test_splitter_non_dict(self):
        with pytest.raises(ConfigError, match="splitter must be a mapping"):
            load_knowledge_from_config(
                {"backend": "memory", "splitter": "bad"}, embed_fn=_fake_embed
            )
