"""soagila_crossagent — Cross-Agent Protocol tool for querying peer SOAGILA instances."""

import json
from datetime import datetime, timezone
from mcp.types import Tool, TextContent


def get_definition() -> Tool:
    return Tool(
        name="soagila_crossagent",
        description=(
            "Query memories from other SOAGILA instances running on this machine. "
            "Use when the user asks about context from another product — "
            "for example 'What did I discuss in the browser?' or 'What memories "
            "does the desktop app have?'. Can list connected agents, query peer "
            "memories, and show agent network status. Requires Pro tier or above "
            "for cross-agent recall."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "action": {
                    "type": "string",
                    "enum": ["peers", "recall", "status"],
                    "description": (
                        "'peers' — list connected SOAGILA agents. "
                        "'recall' — query memories from peer agents. "
                        "'status' — show agent network overview."
                    ),
                },
                "query": {
                    "type": "string",
                    "description": "Query text for cross-agent recall (required when action='recall').",
                },
                "target_product": {
                    "type": "string",
                    "enum": ["vscode", "desktop", "browser", "all"],
                    "description": "Filter peers by product type. Default: 'all'.",
                },
                "max_results": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "description": "Max results per peer agent. Default: 5.",
                },
            },
            "required": ["action"],
        },
    )


async def handle(arguments: dict) -> list[TextContent]:
    action = arguments.get("action", "status")

    from soagila.config import get_settings
    settings = get_settings()

    if action == "peers":
        return await _handle_peers(arguments)
    elif action == "recall":
        # Tier gate: recall requires Pro+
        if settings.tier == "free":
            return [TextContent(type="text", text=json.dumps({
                "error": "Cross-agent recall requires Pro or Enterprise tier.",
                "current_tier": settings.tier,
                "upgrade_url": "https://soagila.com/pricing",
            }))]
        return await _handle_recall(arguments)
    elif action == "status":
        return await _handle_status()
    else:
        return [TextContent(type="text", text=json.dumps({
            "error": f"Unknown action: {action}. Use 'peers', 'recall', or 'status'.",
        }))]


async def _handle_peers(arguments: dict) -> list[TextContent]:
    """List connected peer agents."""
    from soagila.core.cap.discovery import get_peer_agents, get_all_agents, get_self_info

    target_product = arguments.get("target_product")

    self_info = await get_self_info()
    peers = await get_peer_agents(same_project_only=False)

    if target_product and target_product != "all":
        peers = [p for p in peers if p.get("product_type") == target_product]

    # Format product type labels
    product_labels = {
        "vscode": "VS Code Extension",
        "desktop": "Desktop App",
        "browser": "Browser Extension",
    }

    formatted_peers = []
    for p in peers:
        formatted_peers.append({
            "agent_id": p["agent_id"],
            "product": product_labels.get(p["product_type"], p["product_type"]),
            "product_type": p["product_type"],
            "project_name": p.get("project_name", ""),
            "project_hash": p.get("project_hash", "")[:8] + "...",
            "port": p.get("port", 0),
            "capabilities": p.get("capabilities", []),
            "version": p.get("version", ""),
            "last_heartbeat": p.get("last_heartbeat", ""),
        })

    result = {
        "this_agent": {
            "agent_id": self_info["agent_id"] if self_info else "not registered",
            "product": product_labels.get(
                self_info.get("product_type", ""), ""
            ) if self_info else "",
        },
        "peer_count": len(formatted_peers),
        "peers": formatted_peers,
    }

    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_recall(arguments: dict) -> list[TextContent]:
    """Query memories from peer agents."""
    query = arguments.get("query", "")
    if not query:
        return [TextContent(type="text", text=json.dumps({
            "error": "Query is required for cross-agent recall.",
        }))]

    target_product = arguments.get("target_product", "all")
    max_results = arguments.get("max_results", 5)

    from soagila.core.cap.protocol import query_all_peers

    peer_results = await query_all_peers(
        query=query,
        max_results=max_results,
        target_product=target_product,
    )

    # Format results
    product_labels = {
        "vscode": "VS Code Extension",
        "desktop": "Desktop App",
        "browser": "Browser Extension",
    }

    formatted_results = []
    total_memories = 0

    for pr in peer_results:
        source = product_labels.get(
            pr.get("source_product", ""), pr.get("source_product", "unknown")
        )

        # Extract memories from the recall result
        working = pr.get("working", [])
        episodic = pr.get("episodic", [])
        semantic = pr.get("semantic", [])
        count = pr.get("total_results", len(working) + len(episodic) + len(semantic))
        total_memories += count

        formatted_results.append({
            "source": source,
            "source_agent_id": pr.get("source_agent_id", ""),
            "total_results": count,
            "working": working[:max_results],
            "episodic": episodic[:max_results],
            "semantic": semantic[:max_results],
            "receipt_id": pr.get("receipt_id", ""),
        })

    # Create local receipt for the cross-agent query
    receipt_id = None
    try:
        from soagila.core.idl.ledger import create_receipt
        from soagila.core.cap.discovery import get_current_agent_id
        import hashlib

        receipt = await create_receipt(
            receipt_type="cross_agent_query",
            metadata={
                "action": "recall",
                "query": query[:100],
                "peers_queried": len(peer_results),
                "total_memories": total_memories,
                "target_product": target_product,
            },
            context_hash=hashlib.sha256(query.encode()).hexdigest()[:16],
            source_agent_id=get_current_agent_id(),
            cross_agent_ref=formatted_results[0].get("receipt_id") if formatted_results else None,
        )
        receipt_id = receipt.id
    except Exception:
        pass

    result = {
        "query": query,
        "target_product": target_product,
        "peers_queried": len(peer_results),
        "total_memories_found": total_memories,
        "results": formatted_results,
        "receipt_id": receipt_id,
    }

    return [TextContent(type="text", text=json.dumps(result, indent=2))]


async def _handle_status() -> list[TextContent]:
    """Show agent network overview."""
    from soagila.core.cap.discovery import get_self_info, get_peer_agents, get_all_agents
    from soagila.config import get_settings, get_project_hash

    settings = get_settings()
    self_info = await get_self_info()
    all_agents = await get_all_agents(same_project_only=False)
    same_project = await get_peer_agents(same_project_only=True)

    product_labels = {
        "vscode": "VS Code Extension",
        "desktop": "Desktop App",
        "browser": "Browser Extension",
    }

    # Group by product type
    by_product = {}
    for a in all_agents:
        pt = a.get("product_type", "unknown")
        by_product.setdefault(pt, []).append(a["agent_id"])

    result = {
        "status": "active" if self_info else "inactive",
        "this_agent": {
            "agent_id": self_info["agent_id"] if self_info else None,
            "product": product_labels.get(
                self_info.get("product_type", ""), ""
            ) if self_info else "",
            "port": self_info.get("port", 0) if self_info else 0,
            "project_hash": get_project_hash()[:8] + "...",
            "tier": settings.tier,
            "version": settings.app_version,
        },
        "network": {
            "total_agents": len(all_agents),
            "same_project_peers": len(same_project),
            "by_product": {
                product_labels.get(k, k): v for k, v in by_product.items()
            },
        },
        "cross_agent_recall": settings.tier != "free",
        "cross_agent_notifications": settings.tier != "free",
    }

    return [TextContent(type="text", text=json.dumps(result, indent=2))]