from __future__ import annotations

import uuid
from datetime import datetime, timezone
from pathlib import Path
from typing import TYPE_CHECKING, Any

from niannian.personas import LEFT
from niannian.schemas.models import Atom

if TYPE_CHECKING:
    from niannian.brain.brainstem.write_queue import WriteQueue
    from niannian.storage.base import MemoryStore


class LeftStore:
    """小忆 — 碎片采集与打标，只写 raw，不做 Wiki / 推理。"""

    def __init__(
        self,
        data_dir: Path,
        *,
        store: MemoryStore | None = None,
        write_queue: WriteQueue | None = None,
    ) -> None:
        self._data_dir = data_dir
        self._data_dir.mkdir(parents=True, exist_ok=True)
        self._write_queue = write_queue
        if store is None:
            from niannian.storage.local import LocalMemoryStore

            self._store: MemoryStore = LocalMemoryStore(data_dir.parent)
        else:
            self._store = store

    @property
    def store(self) -> MemoryStore:
        return self._store

    def ingest(
        self,
        text: str,
        *,
        tags: list[str] | None = None,
        source: str = "manual",
        project: str = "global",
        meta: dict[str, Any] | None = None,
    ) -> Atom:
        if self._write_queue is not None:
            return self._write_queue.run(
                lambda: self._ingest_impl(
                    text,
                    tags=tags,
                    source=source,
                    project=project,
                    meta=meta,
                )
            )
        return self._ingest_impl(text, tags=tags, source=source, project=project, meta=meta)

    def _ingest_impl(
        self,
        text: str,
        *,
        tags: list[str] | None = None,
        source: str = "manual",
        project: str = "global",
        meta: dict[str, Any] | None = None,
    ) -> Atom:
        atom = Atom(
            id=uuid.uuid4().hex[:12],
            raw_text=text.strip(),
            tags=sorted(set(tags or [])),
            source=source,
            project=project,
            created_at=datetime.now(timezone.utc).isoformat(),
            status="raw",
            meta=dict(meta or {}),
        )
        self._store.append_atom(atom)
        return atom

    def list_atoms(
        self,
        *,
        project: str | None = None,
        limit: int = 500,
        status: str | None = None,
    ) -> list[Atom]:
        return self._store.read_atoms(project, limit=limit, status=status)

    def get(self, atom_id: str) -> Atom | None:
        for a in self.list_atoms(limit=10_000):
            if a.id == atom_id:
                return a
        return None

    def patch_atom_meta(self, atom_id: str, meta_patch: dict[str, Any]) -> Atom | None:
        patch_fn = getattr(self._store, "patch_atom_meta", None)
        if not callable(patch_fn):
            raise NotImplementedError("memory store does not support patch_atom_meta")
        return patch_fn(atom_id, meta_patch)

    @staticmethod
    def trace_line(msg: str) -> str:
        return f"[{LEFT}] {msg}"
