"""Knowledge base implementations for DynaBot."""

from typing import Any

from .base import KnowledgeBase
from .rag import RAGKnowledgeBase
from .retrieval import (
    ChunkMerger,
    ContextFormatter,
    FormatterConfig,
    MergedChunk,
    MergerConfig,
)
from .query import (
    ContextualExpander,
    Message,
    QueryTransformer,
    TransformerConfig,
    create_transformer,
    is_ambiguous_query,
)
from .storage import (
    create_knowledge_backend,
    FileKnowledgeBackend,
    IngestionStatus,
    InMemoryKnowledgeBackend,
    KnowledgeBaseInfo,
    KnowledgeFile,
    KnowledgeResourceBackend,
)
from .ingestion import (
    IngestionResult,
    KnowledgeIngestionManager,
)
from .service import (
    EnsureIngestionResult,
    KnowledgeIngestionService,
    ensure_knowledge_base_ingested,
    get_ingestion_service,
)
from .registry_mixin import AutoIngestionMixin

# Re-export ingestion types for convenience
from dataknobs_xization.ingestion import (
    DirectoryProcessor,
    FilePatternConfig,
    KnowledgeBaseConfig,
    ProcessedDocument,
)

# Re-export hybrid search types
from dataknobs_data.vector.hybrid import (
    FusionStrategy,
    HybridSearchConfig,
    HybridSearchResult,
)

__all__ = [
    # Main knowledge base
    "KnowledgeBase",
    "RAGKnowledgeBase",
    "create_knowledge_base_from_config",
    # Retrieval utilities
    "ChunkMerger",
    "MergedChunk",
    "MergerConfig",
    "ContextFormatter",
    "FormatterConfig",
    # Query utilities
    "QueryTransformer",
    "TransformerConfig",
    "create_transformer",
    "ContextualExpander",
    "Message",
    "is_ambiguous_query",
    # Storage backends
    "KnowledgeResourceBackend",
    "KnowledgeFile",
    "KnowledgeBaseInfo",
    "IngestionStatus",
    "create_knowledge_backend",
    "InMemoryKnowledgeBackend",
    "FileKnowledgeBackend",
    "S3KnowledgeBackend",
    # Ingestion manager (file-backend to vector-store)
    "KnowledgeIngestionManager",
    "IngestionResult",
    # High-level ingestion service
    "KnowledgeIngestionService",
    "EnsureIngestionResult",
    "get_ingestion_service",
    "ensure_knowledge_base_ingested",
    "AutoIngestionMixin",
    # Ingestion types (from xization)
    "DirectoryProcessor",
    "FilePatternConfig",
    "KnowledgeBaseConfig",
    "ProcessedDocument",
    # Hybrid search types
    "FusionStrategy",
    "HybridSearchConfig",
    "HybridSearchResult",
]


def __getattr__(name: str) -> Any:
    """Lazy module-level attribute access for S3KnowledgeBackend.

    Avoids requiring boto3 at import time — only loaded when S3KnowledgeBackend
    is actually accessed.
    """
    if name == "S3KnowledgeBackend":
        from .storage import S3KnowledgeBackend

        return S3KnowledgeBackend
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


async def create_knowledge_base_from_config(config: dict[str, Any]) -> KnowledgeBase:
    """Create knowledge base from configuration.

    Args:
        config: Knowledge base configuration with:
            - type: Type of knowledge base (currently only 'rag' supported)
            - vector_store: Vector store configuration
            - embedding_provider: LLM provider for embeddings
            - embedding_model: Model to use for embeddings
            - chunking: Optional chunking configuration
            - documents_path: Optional path to load documents
            - document_pattern: Optional file pattern

    Returns:
        Configured knowledge base instance

    Raises:
        ValueError: If knowledge base type is not supported

    Example:
        ```python
        config = {
            "type": "rag",
            "vector_store": {
                "backend": "memory",
                "dimensions": 384
            },
            "embedding_provider": "echo",
            "embedding_model": "test"
        }
        kb = await create_knowledge_base_from_config(config)
        ```
    """
    kb_type = config.get("type", "rag").lower()

    if kb_type == "rag":
        return await RAGKnowledgeBase.from_config(config)
    else:
        raise ValueError(
            f"Unknown knowledge base type: {kb_type}. " f"Available types: rag"
        )
