"""Beaver memory 应用服务。

这层不是新的 memory 实现，而是对现有 `MemoryStore + MemorySnapshot` 的应用层包装。

目标只有三个：
1. 把“本轮运行前需要 refresh live state”这件事集中到一个地方
2. 把“给 context builder 的只能是 frozen snapshot”这条规则写死
3. 让 `AgentLoop` 不再直接操作 `MemoryStore` 细节

设计边界：
1. 记忆实际读写逻辑仍然在 `beaver.memory.curated.store.MemoryStore`
2. memory tool 仍然直接写 store
3. 本服务只负责 runtime 接入策略，不负责 CRUD 业务本身
"""

from __future__ import annotations

from pathlib import Path

from beaver.memory.curated.snapshot import MemorySnapshot, capture_memory_snapshot
from beaver.memory.curated.store import MemoryStore


class MemoryService:
    """统一封装 runtime 对 curated memory 的访问方式。"""

    def __init__(
        self,
        root: str | Path,
        *,
        store: MemoryStore | None = None,
    ) -> None:
        self.root = Path(root)
        self.store = store or MemoryStore(self.root)
        self._snapshot: MemorySnapshot | None = None

    def initialize(self) -> None:
        """启动时加载一次磁盘内容，建立首份 frozen snapshot 基线。"""

        self.store.load_from_disk()
        self._snapshot = capture_memory_snapshot(self.store)

    def reload_for_new_run(self) -> None:
        """每次新 run 开始前刷新 live state。

        这是 Beaver memory policy 的关键点：
        - 上一次会话中通过 tool 写入的持久记忆，下一次运行应该能看到
        - 但同一次 run 中途写入的新记忆，不应反向修改当前 frozen snapshot
        """

        self.store.load_from_disk()
        self._snapshot = capture_memory_snapshot(self.store)

    def capture_snapshot_for_run(self) -> MemorySnapshot:
        """Capture a per-run frozen snapshot without mutating shared runtime state."""

        store = MemoryStore(self.root)
        store.load_from_disk()
        return capture_memory_snapshot(store)

    def get_snapshot(self) -> MemorySnapshot:
        """获取当前 run 应注入 system prompt 的 frozen snapshot。"""

        if self._snapshot is None:
            # 兜底场景：如果调用方绕过 initialize/reload，首次读取时仍建立一份快照。
            self._snapshot = capture_memory_snapshot(self.store)
        return self._snapshot

    def get_store(self) -> MemoryStore:
        """暴露底层 store 给需要直接调用 CRUD 的工具层。"""

        return self.store
