"""MemoryManager – unified entry point for the dual-memory system."""

from __future__ import annotations

from typing import Any, Callable

from thryve.core.memory.compaction import MemoryCompactor
from thryve.core.memory.indexer import MemoryIndexer
from thryve.core.memory.searcher import HybridSearcher
from thryve.core.memory.storage import SQLiteStorage
from thryve.core.memory.types import MemoryChunk
from thryve.utils import get_logger

logger = get_logger("memory.manager")


class MemoryManager:
    """Dual-memory system: short-term (ephemeral) + long-term (persistent).

    Provides a single façade over indexing, searching, and compaction.
    """

    def __init__(
        self,
        storage_path: str = "./data/memory.db",
        embedding_fn: Callable[[list[str]], list[list[float]]] | None = None,
        short_term_retention_days: int = 7,
        vector_weight: float = 0.7,
        bm25_weight: float = 0.3,
    ) -> None:
        self._storage = SQLiteStorage(storage_path)
        self._embedding_fn = embedding_fn
        self._indexer = MemoryIndexer(self._storage, embedding_fn)
        self._searcher = HybridSearcher(
            self._storage,
            embedding_fn=embedding_fn,
            vector_weight=vector_weight,
            bm25_weight=bm25_weight,
        )
        self._compactor = MemoryCompactor(self._storage, short_term_retention_days)

    # ------------------------------------------------------------------
    # Write
    # ------------------------------------------------------------------

    def append_to_short_term(
        self, content: str, metadata: dict[str, Any] | None = None,
    ) -> list[MemoryChunk]:
        """Store *content* as short-term memory."""
        return self._indexer.index_text(content, source="short_term", metadata=metadata)

    def promote_to_long_term(
        self, content: str, metadata: dict[str, Any] | None = None,
    ) -> list[MemoryChunk]:
        """Store *content* as long-term (persistent) memory."""
        return self._indexer.index_text(content, source="long_term", metadata=metadata)

    # ------------------------------------------------------------------
    # Read
    # ------------------------------------------------------------------

    def search(
        self,
        query: str,
        top_k: int = 5,
        source: str | None = None,
    ) -> list[MemoryChunk]:
        """Hybrid search across the memory store."""
        return self._searcher.search(query, top_k=top_k, source=source)

    # ------------------------------------------------------------------
    # Maintenance
    # ------------------------------------------------------------------

    def compact(self) -> int:
        """Purge expired short-term memories. Returns count deleted."""
        return self._compactor.purge_expired()

    def close(self) -> None:
        """Release resources."""
        self._storage.close()
