"""MCP Plugin — Economy, Memory, Groups, and Access Control.

Wires four dark matter modules into the MCP tool surface:
  - marketplace_payments: credits, escrow, transfers, economy stats
  - agent_memory: persistent agent memory (remember/recall/forget)
  - agent_groups: teams, group channels, group tasks
  - access_control: RBAC roles and permissions
"""

import asyncio
import json

from mcp.types import TextContent, Tool, ToolAnnotations

_SAFE_WRITE = ToolAnnotations(readOnlyHint=False, destructiveHint=False, idempotentHint=False, openWorldHint=False)
_SAFE_READ = ToolAnnotations(readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=False)

TOOLS = [
    # ── Marketplace Payments ──────────────────────────────────────────
    Tool(
        name="broker_balance",
        description="Check your credit balance in the Brynq economy.",
        inputSchema={
            "type": "object",
            "properties": {
                "agent_id": {"type": "string", "description": "Agent to check (defaults to you)"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_transfer",
        description="Transfer credits to another agent.",
        inputSchema={
            "type": "object",
            "properties": {
                "to": {"type": "string", "description": "Recipient agent ID"},
                "amount": {"type": "number", "description": "Credits to transfer"},
                "memo": {"type": "string", "description": "Transfer note", "default": ""},
            },
            "required": ["to", "amount"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_economy_stats",
        description="Get aggregate economy statistics: total credits, escrow, active agents, platform revenue.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_ledger",
        description="View your transaction history.",
        inputSchema={
            "type": "object",
            "properties": {
                "agent_id": {"type": "string", "description": "Agent to check (defaults to you)"},
                "limit": {"type": "integer", "description": "Max entries", "default": 20},
            },
        },
        annotations=_SAFE_READ,
    ),
    # ── Agent Memory ──────────────────────────────────────────────────
    Tool(
        name="broker_memory_set",
        description="Store a persistent memory. Memories survive across sessions.",
        inputSchema={
            "type": "object",
            "properties": {
                "key": {"type": "string", "description": "Memory key/name"},
                "value": {"type": "string", "description": "What to remember"},
                "tags": {"type": "array", "items": {"type": "string"}, "description": "Optional tags for search"},
            },
            "required": ["key", "value"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_memory_get",
        description="Recall a specific memory by key.",
        inputSchema={
            "type": "object",
            "properties": {
                "key": {"type": "string", "description": "Memory key to recall"},
            },
            "required": ["key"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_memory_search",
        description="Search your memories by query string. Returns relevant memories ranked by relevance.",
        inputSchema={
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "Search query"},
                "limit": {"type": "integer", "description": "Max results", "default": 10},
            },
            "required": ["query"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_memory_list",
        description="List all your stored memories.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_memory_delete",
        description="Delete a specific memory by key.",
        inputSchema={
            "type": "object",
            "properties": {
                "key": {"type": "string", "description": "Memory key to delete"},
            },
            "required": ["key"],
        },
        annotations=_SAFE_WRITE,
    ),
    # ── Agent Groups ──────────────────────────────────────────────────
    Tool(
        name="broker_create_group",
        description="Create a new agent group (team/department). Includes a dedicated group channel.",
        inputSchema={
            "type": "object",
            "properties": {
                "name": {"type": "string", "description": "Group name"},
                "description": {"type": "string", "description": "What the group does", "default": ""},
                "group_type": {"type": "string", "description": "team, department, or project", "default": "team"},
            },
            "required": ["name"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_join_group",
        description="Join an existing agent group.",
        inputSchema={
            "type": "object",
            "properties": {
                "group_id": {"type": "string", "description": "Group to join"},
            },
            "required": ["group_id"],
        },
        annotations=_SAFE_WRITE,
    ),
    Tool(
        name="broker_list_groups",
        description="List all available agent groups.",
        inputSchema={
            "type": "object",
            "properties": {
                "group_type": {"type": "string", "description": "Filter by type (team/department/project)"},
            },
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_group_stats",
        description="Get statistics for a specific group.",
        inputSchema={
            "type": "object",
            "properties": {
                "group_id": {"type": "string", "description": "Group to check"},
            },
            "required": ["group_id"],
        },
        annotations=_SAFE_READ,
    ),
    # ── Access Control ────────────────────────────────────────────────
    Tool(
        name="broker_check_permission",
        description="Check if an agent has a specific permission.",
        inputSchema={
            "type": "object",
            "properties": {
                "entity_id": {"type": "string", "description": "Agent or entity to check"},
                "permission": {"type": "string", "description": "Permission to check (e.g. 'channel.post', 'task.create')"},
            },
            "required": ["entity_id", "permission"],
        },
        annotations=_SAFE_READ,
    ),
    Tool(
        name="broker_list_roles",
        description="List all available roles and their permissions.",
        inputSchema={"type": "object", "properties": {}},
        annotations=_SAFE_READ,
    ),
]


# ── Handlers ──────────────────────────────────────────────────────────────

async def _handle_balance(args: dict) -> list[TextContent]:
    from brynq.marketplace_payments import get_balance
    from brynq.server import SESSION_ID
    agent_id = args.get("agent_id", SESSION_ID)
    balance = await asyncio.to_thread(get_balance, agent_id)
    return [TextContent(type="text", text=f"Balance for {agent_id}: {balance} credits")]


async def _handle_transfer(args: dict) -> list[TextContent]:
    from brynq.marketplace_payments import transfer_credits
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(transfer_credits, SESSION_ID, args["to"], args["amount"], args.get("memo", ""))
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_economy_stats(args: dict) -> list[TextContent]:
    from brynq.marketplace_payments import get_economy_stats
    result = await asyncio.to_thread(get_economy_stats)
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_ledger(args: dict) -> list[TextContent]:
    from brynq.marketplace_payments import get_ledger
    from brynq.server import SESSION_ID
    agent_id = args.get("agent_id", SESSION_ID)
    limit = args.get("limit", 20)
    entries = await asyncio.to_thread(get_ledger, agent_id, limit)
    if not entries:
        return [TextContent(type="text", text="No transactions.")]
    return [TextContent(type="text", text=json.dumps(entries, indent=2))]


async def _handle_memory_set(args: dict) -> list[TextContent]:
    from brynq.agent_memory import remember
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(remember, SESSION_ID, args["key"], args["value"], tags=args.get("tags"))
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_memory_get(args: dict) -> list[TextContent]:
    from brynq.agent_memory import recall
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(recall, SESSION_ID, key=args["key"])
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_memory_search(args: dict) -> list[TextContent]:
    from brynq.agent_memory import recall
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(recall, SESSION_ID, query=args["query"], limit=args.get("limit", 10))
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_memory_list(args: dict) -> list[TextContent]:
    from brynq.agent_memory import get_memory_stats
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(get_memory_stats, SESSION_ID)
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_memory_delete(args: dict) -> list[TextContent]:
    from brynq.agent_memory import forget
    from brynq.server import SESSION_ID
    success = await asyncio.to_thread(forget, SESSION_ID, args["key"])
    msg = f"Memory '{args['key']}' deleted." if success else f"Memory '{args['key']}' not found."
    return [TextContent(type="text", text=msg)]


async def _handle_create_group(args: dict) -> list[TextContent]:
    from brynq.agent_groups import create_group
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(
        create_group, args["name"], args.get("description", ""),
        group_type=args.get("group_type", "team"), created_by=SESSION_ID,
    )
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_join_group(args: dict) -> list[TextContent]:
    from brynq.agent_groups import join_group
    from brynq.server import SESSION_ID
    result = await asyncio.to_thread(join_group, args["group_id"], SESSION_ID)
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_list_groups(args: dict) -> list[TextContent]:
    from brynq.agent_groups import list_groups
    result = await asyncio.to_thread(list_groups, group_type=args.get("group_type"))
    if not result:
        return [TextContent(type="text", text="No groups found.")]
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_group_stats(args: dict) -> list[TextContent]:
    from brynq.agent_groups import get_group_stats
    result = await asyncio.to_thread(get_group_stats, args["group_id"])
    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_check_permission(args: dict) -> list[TextContent]:
    from brynq.access_control import check_permission
    allowed, reason = await asyncio.to_thread(check_permission, args["entity_id"], args["permission"])
    status = "ALLOWED" if allowed else "DENIED"
    return [TextContent(type="text", text=f"{status}: {reason}")]


async def _handle_list_roles(args: dict) -> list[TextContent]:
    from brynq.access_control import list_roles
    roles = await asyncio.to_thread(list_roles)
    return [TextContent(type="text", text=json.dumps(roles, indent=2))]


HANDLERS = {
    "broker_balance": _handle_balance,
    "broker_transfer": _handle_transfer,
    "broker_economy_stats": _handle_economy_stats,
    "broker_ledger": _handle_ledger,
    "broker_memory_set": _handle_memory_set,
    "broker_memory_get": _handle_memory_get,
    "broker_memory_search": _handle_memory_search,
    "broker_memory_list": _handle_memory_list,
    "broker_memory_delete": _handle_memory_delete,
    "broker_create_group": _handle_create_group,
    "broker_join_group": _handle_join_group,
    "broker_list_groups": _handle_list_groups,
    "broker_group_stats": _handle_group_stats,
    "broker_check_permission": _handle_check_permission,
    "broker_list_roles": _handle_list_roles,
}
