"""Cross-session memory management using LangGraph store.

Provides direct CRUD operations on the /.memories/ store namespace,
independent of the agent. Used by the /memory command and auto-learning triggers.
"""

from __future__ import annotations

from datetime import UTC, datetime
from typing import Any


async def list_memories(store: Any, namespace: tuple[str, ...] | None = None) -> list[dict]:
    """List all memory entries in the store.

    Args:
        store: AsyncSqliteStore instance.
        namespace: Store namespace tuple. Defaults to ("filesystem",).

    Returns:
        List of dicts with key, preview, modified_at.
    """
    ns = namespace or ("filesystem",)
    results = []
    try:
        items = await store.asearch(ns, limit=100)
        for item in items:
            value = item.value if hasattr(item, "value") else {}
            content = value.get("content", [])
            preview = ""
            if isinstance(content, list) and content:
                preview = content[0][:80] if content[0] else ""
            elif isinstance(content, str):
                preview = content[:80]
            results.append({
                "key": item.key,
                "preview": preview,
                "modified_at": value.get("modified_at", ""),
            })
    except Exception:
        pass
    return results


async def read_memory(
    store: Any, key: str, namespace: tuple[str, ...] | None = None,
) -> str | None:
    """Read a memory entry by key.

    Args:
        store: AsyncSqliteStore instance.
        key: The memory key (e.g., "user_preferences.md").
        namespace: Store namespace tuple.

    Returns:
        The memory content as a string, or None if not found.
    """
    ns = namespace or ("filesystem",)
    try:
        item = await store.aget(ns, key)
        if item is None:
            return None
        value = item.value if hasattr(item, "value") else {}
        content = value.get("content", [])
        if isinstance(content, list):
            return "\n".join(content)
        return str(content)
    except Exception:
        return None


async def write_memory(
    store: Any,
    key: str,
    content: str,
    namespace: tuple[str, ...] | None = None,
) -> None:
    """Write or overwrite a memory entry.

    Args:
        store: AsyncSqliteStore instance.
        key: The memory key.
        content: The content to store.
        namespace: Store namespace tuple.
    """
    ns = namespace or ("filesystem",)
    now = datetime.now(UTC).isoformat()
    lines = content.split("\n")
    value = {
        "content": lines,
        "created_at": now,
        "modified_at": now,
    }
    await store.aput(ns, key, value)


async def delete_memory(
    store: Any, key: str, namespace: tuple[str, ...] | None = None,
) -> bool:
    """Delete a memory entry.

    Args:
        store: AsyncSqliteStore instance.
        key: The memory key to delete.
        namespace: Store namespace tuple.

    Returns:
        True if deleted, False if not found.
    """
    ns = namespace or ("filesystem",)
    try:
        item = await store.aget(ns, key)
        if item is None:
            return False
        await store.adelete(ns, key)
        return True
    except Exception:
        return False


async def clear_memories(
    store: Any, namespace: tuple[str, ...] | None = None,
) -> int:
    """Delete all memory entries in the namespace.

    Args:
        store: AsyncSqliteStore instance.
        namespace: Store namespace tuple.

    Returns:
        Number of entries deleted.
    """
    ns = namespace or ("filesystem",)
    count = 0
    try:
        items = await store.asearch(ns, limit=500)
        for item in items:
            await store.adelete(ns, item.key)
            count += 1
    except Exception:
        pass
    return count


# Auto-learning trigger constants
AUTO_REMEMBER_INTERVAL = 15  # Suggest /remember every N messages
AUTO_REMEMBER_MIN_MESSAGES = 8  # Don't suggest until this many messages
