"""Tool handlers — the code that runs when the LLM calls Coppermind tools.

Rules for Hermes plugin handlers:
1. Signature: def handler(args: dict, **kwargs) -> str
2. Always return a JSON string (success and errors alike)
3. Never raise exceptions — catch everything
4. Accept **kwargs for forward compatibility
"""

import json
import logging

from . import client

logger = logging.getLogger("coppermind")


def coppermind_search(args: dict, **kwargs) -> str:
    """Search memory for relevant information.

    Called by the LLM when it needs to look up specific past context.
    The automatic pre_llm_call hook handles basic retrieval — this tool
    is for deeper, explicit searches the agent decides to perform.
    """
    query = args.get("query", "").strip()
    if not query:
        return json.dumps({"error": "No search query provided"})

    limit = args.get("limit", 5)
    if not isinstance(limit, int) or limit < 1:
        limit = 5
    limit = min(limit, 20)  # Cap at 20

    try:
        result = client.search_memory(query=query, limit=limit)

        # Format fragments for the LLM
        fragments = result.get("fragments", [])
        if not fragments:
            # Fall back to context string if present
            context = result.get("context", "")
            if context:
                return json.dumps({
                    "query": query,
                    "found": True,
                    "memories": context,
                })
            return json.dumps({
                "query": query,
                "found": False,
                "message": "No memories found matching your query.",
            })

        memories = []
        for f in fragments[:limit]:
            content = (
                f.get("content")
                or f.get("contentSummary")
                or f.get("text")
                or ""
            )
            if content:
                memories.append({
                    "content": content[:500],
                    "created_at": f.get("createdAt", ""),
                    "tags": f.get("tags", []),
                })

        return json.dumps({
            "query": query,
            "found": True,
            "count": len(memories),
            "memories": memories,
        })

    except client.CoppermindError as e:
        logger.warning("coppermind_search failed: %s", e)
        return json.dumps({
            "error": f"Memory search failed: {e}",
            "query": query,
        })
    except Exception as e:
        logger.error("Unexpected error in coppermind_search: %s", e)
        return json.dumps({
            "error": f"Unexpected error: {e}",
            "query": query,
        })


def coppermind_recall(args: dict, **kwargs) -> str:
    """Recall recent memories for the current user.

    Returns a broad view of recent memory context, useful at the
    start of a new session or when the agent needs general context.
    """
    user_id = args.get("user_id") or client.USER_ID

    try:
        result = client.get_memory(user_id=user_id)

        context = result.get("context", "")
        if context:
            return json.dumps({
                "found": True,
                "memories": context,
            })

        return json.dumps({
            "found": False,
            "message": "No memories found for this user.",
        })

    except client.CoppermindError as e:
        logger.warning("coppermind_recall failed: %s", e)
        return json.dumps({"error": f"Memory recall failed: {e}"})
    except Exception as e:
        logger.error("Unexpected error in coppermind_recall: %s", e)
        return json.dumps({"error": f"Unexpected error: {e}"})
