import json

from fastapi import APIRouter, Request
from starlette.responses import JSONResponse

from backend.mcp_runtime import _mcp_call, _mcp_discover_all, _mcp_get_cache


router = APIRouter()


@router.get("/api/mcp/status")
def api_mcp_status():
    """Return per-server MCP discovery status and cached tools."""
    cache = _mcp_get_cache()
    servers: list[dict] = []
    for name, entry in cache.items():
        servers.append({
            "name": name,
            "ok": entry.get("ok", False),
            "error": entry.get("error"),
            "tools": entry.get("tools", []),
            "discovered_at": entry.get("ts"),
        })
    return {"servers": servers}


@router.post("/api/mcp/refresh")
def api_mcp_refresh():
    """Re-discover tools on all configured MCP servers (blocking)."""
    _mcp_discover_all()
    return api_mcp_status()


@router.api_route("/api/mcp/call", methods=["POST", "GET"])
async def api_mcp_call(request: Request):
    """Call one MCP tool from the settings UI and return parsed output when possible."""
    try:
        server = ""
        tool = ""
        arguments = {}
        if request.method == "GET":
            query = request.query_params
            server = str(query.get("server", "")).strip()
            tool = str(query.get("tool", "")).strip()
            raw_args = str(query.get("arguments", "")).strip()
            if raw_args:
                try:
                    parsed_args = json.loads(raw_args)
                    if isinstance(parsed_args, dict):
                        arguments = parsed_args
                except Exception:
                    arguments = {}
        else:
            body = await request.json()
            server = str(body.get("server", "")).strip()
            tool = str(body.get("tool", "")).strip()
            arguments = body.get("arguments")

        if not isinstance(arguments, dict):
            arguments = {}
        if not server:
            return JSONResponse({"ok": False, "error": "server is required"}, status_code=400)
        if not tool:
            return JSONResponse({"ok": False, "error": "tool is required"}, status_code=400)

        text = _mcp_call(server, tool, arguments)
        error_prefixes = (
            "Unknown MCP server",
            "MCP server '",
            "MCP SDK is not installed",
            "MCP call failed",
            "MCP error:",
            "MCP call to",
            "MCP call error:",
        )
        if any(text.startswith(prefix) for prefix in error_prefixes):
            return JSONResponse({"ok": False, "error": text}, status_code=400)

        parsed = None
        try:
            parsed = json.loads(text)
        except Exception:
            try:
                import ast

                maybe = ast.literal_eval(text)
                if isinstance(maybe, (dict, list, str, int, float, bool)) or maybe is None:
                    parsed = maybe
            except Exception:
                parsed = None

        return {"ok": True, "result_text": text, "result": parsed}
    except Exception as exc:
        return JSONResponse({"ok": False, "error": str(exc)}, status_code=500)