#!/usr/bin/env python3
"""
Memory interface for Clawdbot runtime integration.

This module provides the bridge between Clawdbot (Node.js) and the
Python memory system. It can be used in three ways:

1. CLI mode: Called as subprocess from Node.js
   python memory_interface.py search "query" --guild 123 --limit 5
   python memory_interface.py context "message text" --guild 123 --user 456

2. JSON-RPC mode: Run as a simple server
   python memory_interface.py serve --port 9876

3. Direct import: From other Python code
   from memory_interface import get_context_for_message, remember
"""

import sys
import os
import json
import argparse
from typing import Optional, List, Dict, Any

# Add workspace to path for imports
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Import from memory-retrieval.py (hyphenated filename)
import importlib.util
spec = importlib.util.spec_from_file_location(
    "memory_retrieval",
    os.path.join(os.path.dirname(os.path.abspath(__file__)), "memory-retrieval.py")
)
memory_retrieval = importlib.util.module_from_spec(spec)
spec.loader.exec_module(memory_retrieval)

search_memories = memory_retrieval.search_memories
add_memory = memory_retrieval.add_memory
get_recent_memories = memory_retrieval.get_recent_memories
supersede_memory = memory_retrieval.supersede_memory
get_memory_stats = memory_retrieval.get_memory_stats
ensure_secure_permissions = memory_retrieval.ensure_secure_permissions


def get_context_for_message(
    message: str,
    guild_id: Optional[str] = None,
    channel_id: Optional[str] = None,
    user_id: Optional[str] = None,
    limit: int = 5
) -> str:
    """
    Get relevant memory context for responding to a message.
    Call this before generating a response to inject memory.

    Args:
        message: The incoming message text
        guild_id: Discord guild ID (for scoping)
        channel_id: Discord channel ID
        user_id: Discord user ID
        limit: Maximum number of memories to return

    Returns:
        Formatted string of relevant memories for prompt injection
    """
    # Security check
    ensure_secure_permissions(warn=False)

    # Search for relevant memories
    results = search_memories(
        query=message,
        guild_id=guild_id,
        user_id=user_id,
        limit=limit
    )

    if not results:
        # Fall back to recent memories for this guild
        results = get_recent_memories(guild_id=guild_id, limit=3)

    if not results:
        return ""

    # Format for context injection
    lines = ["[Relevant Memories]"]
    for r in results:
        mem_type = r.get('memory_type', 'fact')
        content = r.get('content', '')
        # Truncate long content
        if len(content) > 200:
            content = content[:200] + "..."
        lines.append(f"- [{mem_type}] {content}")

    return "\n".join(lines)


def should_remember(response_text: str) -> bool:
    """
    Check if the bot's response indicates something should be remembered.
    """
    triggers = [
        "i'll remember",
        "i've noted",
        "got it",
        "noted",
        "understood",
        "i'll keep that in mind",
        "remembered",
    ]
    lower = response_text.lower()
    return any(t in lower for t in triggers)


def remember(
    content: str,
    memory_type: str = "fact",
    guild_id: Optional[str] = None,
    channel_id: Optional[str] = None,
    user_id: Optional[str] = None,
    source: str = "conversation"
) -> Dict[str, Any]:
    """
    Store a new memory.

    Args:
        content: What to remember
        memory_type: Type (fact, preference, event, relationship, project, person, security)
        guild_id: Discord guild ID
        channel_id: Discord channel ID
        user_id: Discord user ID who provided the info
        source: Where this memory came from

    Returns:
        Dict with memory_id and status
    """
    ensure_secure_permissions(warn=False)

    try:
        memory_id = add_memory(
            content=content,
            memory_type=memory_type,
            guild_id=guild_id,
            channel_id=channel_id,
            user_id=user_id,
            source=source
        )
        return {"success": True, "memory_id": memory_id}
    except Exception as e:
        return {"success": False, "error": str(e)}


def update_memory(
    old_id: int,
    new_content: str,
    reason: str = "updated"
) -> Dict[str, Any]:
    """
    Update an existing memory by superseding it.

    Args:
        old_id: ID of the memory to update
        new_content: New content
        reason: Why it's being updated

    Returns:
        Dict with new memory_id and status
    """
    ensure_secure_permissions(warn=False)

    try:
        new_id = supersede_memory(old_id, new_content, reason)
        return {"success": True, "old_id": old_id, "new_id": new_id}
    except Exception as e:
        return {"success": False, "error": str(e)}


def search(
    query: str,
    guild_id: Optional[str] = None,
    memory_type: Optional[str] = None,
    limit: int = 10
) -> List[Dict[str, Any]]:
    """
    Search memories.

    Args:
        query: Search query
        guild_id: Filter to guild
        memory_type: Filter to type
        limit: Max results

    Returns:
        List of matching memories
    """
    ensure_secure_permissions(warn=False)

    return search_memories(
        query=query,
        guild_id=guild_id,
        memory_type=memory_type,
        limit=limit
    )


def stats() -> Dict[str, Any]:
    """Get memory statistics."""
    ensure_secure_permissions(warn=False)
    return get_memory_stats()


# CLI Interface
def main():
    parser = argparse.ArgumentParser(description="Clawdbot Memory Interface")
    subparsers = parser.add_subparsers(dest="command", help="Command")

    # Search command
    search_p = subparsers.add_parser("search", help="Search memories")
    search_p.add_argument("query", help="Search query")
    search_p.add_argument("--guild", help="Guild ID filter")
    search_p.add_argument("--type", help="Memory type filter")
    search_p.add_argument("--limit", type=int, default=10, help="Max results")

    # Context command (for message processing)
    ctx_p = subparsers.add_parser("context", help="Get context for message")
    ctx_p.add_argument("message", help="Message text")
    ctx_p.add_argument("--guild", help="Guild ID")
    ctx_p.add_argument("--channel", help="Channel ID")
    ctx_p.add_argument("--user", help="User ID")
    ctx_p.add_argument("--limit", type=int, default=5, help="Max memories")

    # Remember command
    rem_p = subparsers.add_parser("remember", help="Store a memory")
    rem_p.add_argument("content", help="Content to remember")
    rem_p.add_argument("--type", default="fact", help="Memory type")
    rem_p.add_argument("--guild", help="Guild ID")
    rem_p.add_argument("--channel", help="Channel ID")
    rem_p.add_argument("--user", help="User ID")

    # Stats command
    subparsers.add_parser("stats", help="Get memory statistics")

    args = parser.parse_args()

    if args.command == "search":
        results = search(
            query=args.query,
            guild_id=args.guild,
            memory_type=getattr(args, 'type', None),
            limit=args.limit
        )
        print(json.dumps(results, indent=2))

    elif args.command == "context":
        context = get_context_for_message(
            message=args.message,
            guild_id=args.guild,
            channel_id=args.channel,
            user_id=args.user,
            limit=args.limit
        )
        print(context)

    elif args.command == "remember":
        result = remember(
            content=args.content,
            memory_type=getattr(args, 'type', 'fact'),
            guild_id=args.guild,
            channel_id=args.channel,
            user_id=args.user
        )
        print(json.dumps(result))

    elif args.command == "stats":
        print(json.dumps(stats(), indent=2))

    else:
        parser.print_help()
        sys.exit(1)


if __name__ == "__main__":
    main()
