from __future__ import annotations

from typing import Any

from niannian.memory.adult_redaction import AdultRedactor
from niannian.memory.ingest import normalize_ingest_meta
from niannian.personas import BRAINSTEM
from niannian.schemas.models import Atom


class Orchestrator:
    """小枢 — ingest / dream 编排；回忆统一走 RecallEngine。"""

    def __init__(
        self,
        left,
        cerebellum,
        hippocampus,
        right,
        router,
        *,
        show_trace: bool = True,
        config: dict[str, Any] | None = None,
    ) -> None:
        self._left = left
        self._cerebellum = cerebellum
        self._hippocampus = hippocampus
        self._right = right
        self._router = router
        self._show_trace = show_trace
        self._config = config or {}
        self._redactor = AdultRedactor.from_app_config(self._config)

    def ingest(
        self,
        text: str,
        *,
        tags: list[str] | None = None,
        source: str = "manual",
        project: str = "global",
        meta: dict[str, Any] | None = None,
    ) -> tuple[Atom, list[str]]:
        trace: list[str] = []
        if self._show_trace:
            trace.append(f"[{BRAINSTEM}] ingest project={project}")

        merged_meta = normalize_ingest_meta(dict(meta or {}))
        encoded = self._redactor.encode_for_storage(
            text,
            project=project,
            tags=tags,
            meta=merged_meta,
        )
        if encoded.redacted:
            merged_meta.update(encoded.meta_patch)
            if self._show_trace:
                refs = encoded.meta_patch.get("adult_redaction", {}).get("refs", [])
                trace.append(self._left.trace_line(f"露骨占位 {len(refs)} 段 → $id$"))

        atom = self._left.ingest(
            encoded.text,
            tags=tags,
            source=source,
            project=project,
            meta=merged_meta,
        )
        if self._show_trace:
            trace.append(self._left.trace_line(f"atom #{atom.id}"))
        recent = self._left.list_atoms(project=project, limit=50)
        touched = self._cerebellum.compile_from_atoms(recent)
        if touched and self._show_trace:
            trace.append(self._cerebellum.trace_line(f"wiki 更新 {len(touched)} 概念"))
        return atom, trace

    def dream(self, *, project: str = "global") -> dict:
        atoms = self._left.list_atoms(project=project, limit=500)
        return self._hippocampus.dream(atoms)
