"""
Detection mask CLI (MCP-only).

Usage:
  python -X utf8 tools/detect_mask.py --det "person ." data/example.jpeg

Behavior:
    - Calls DetectorServer.detect over stdio (MCP) and prints JSON {mask_path, meta}.
    - All logging is handled inside the detector server.
"""
from __future__ import annotations

import argparse
import asyncio
import json
import os
import pathlib
import sys
from pathlib import Path
from typing import Any, Dict

try:
    from mcp.client.session import ClientSession  # type: ignore
    from mcp.client.stdio import stdio_client, StdioServerParameters  # type: ignore
except Exception:  # pragma: no cover
    ClientSession = None  # type: ignore
    stdio_client = None  # type: ignore
    StdioServerParameters = None  # type: ignore


def _extract_json_from_call_result(res: Any) -> Dict[str, Any] | None:
    """Best-effort extraction of a JSON payload from an MCP tool result."""
    try:
        content = getattr(res, "content", None)
        if content is None and isinstance(res, dict):
            return res
        if content is not None:
            for c in content:
                if isinstance(c, dict):
                    ctype = c.get("type")
                    if ctype in ("json", "application/json"):
                        return c.get("json") or c.get("data") or c.get("value")
                    if ctype == "text" and isinstance(c.get("text"), str):
                        try:
                            return json.loads(c.get("text"))
                        except Exception:
                            continue
                else:
                    ctype = getattr(c, "type", None)
                    if ctype in ("json", "application/json"):
                        return getattr(c, "json", None) or getattr(c, "data", None) or getattr(c, "value", None)
                    if ctype == "text":
                        txt = getattr(c, "text", None)
                        if isinstance(txt, str):
                            try:
                                return json.loads(txt)
                            except Exception:
                                continue
    except Exception:
        pass
    return None


_REPO_ROOT = pathlib.Path(__file__).resolve().parents[1]
if str(_REPO_ROOT) not in sys.path:
    sys.path.insert(0, str(_REPO_ROOT))


def main() -> int:
    p = argparse.ArgumentParser(description="Detection mask via MCP detector server")
    p.add_argument("image", help="Path to input image")
    p.add_argument("--det", required=True, help="Detection prompt (dot-terminated)")
    p.add_argument("--backend", help="Force detector backend (grounded-sam-2 | auto)")
    p.add_argument("--grounded-dir", help="Path to Grounded-SAM-2 checkout (sets GROUNDED_SAM2_DIR)")
    args = p.parse_args()

    ipath = Path(args.image)
    if not ipath.exists():
        print(json.dumps({"mask_path": "", "error": f"image not found: {ipath}"}), flush=True)
        return 2

    # if ClientSession is None or stdio_client is None or StdioServerParameters is None:
    #     print(json.dumps({"mask_path": "", "error": "MCP SDK not installed"}), flush=True)
    #     return 1

    # Propagate backend-related environment before spawning server
    if args.backend:
        os.environ["DETECTOR_BACKEND"] = args.backend
    if args.grounded_dir:
        os.environ["GROUNDED_SAM2_DIR"] = args.grounded_dir
    if os.getenv("DETECTOR_DEBUG"):
        print(
            json.dumps(
                {
                    "cli_backend": args.backend,
                    "env_DETECTOR_BACKEND": os.getenv("DETECTOR_BACKEND"),
                    "env_GROUNDED_SAM2_DIR": os.getenv("GROUNDED_SAM2_DIR"),
                }
            ),
            file=sys.stderr,
            flush=True,
        )

    try:
        async def _call_detector() -> Dict[str, Any]:
            # Create environment that includes current environment plus our custom variables
            env = os.environ.copy()
            
            params = StdioServerParameters(
                command=sys.executable,
                args=["-m", "mcp.servers.detector_server"],
                env=env,
            )
            async with stdio_client(params) as (read, write):
                async with ClientSession(read, write) as session:
                    await session.initialize()
                    tool_args = {"det_prompt": args.det, "image_path": str(ipath)}
                    if args.backend:
                        tool_args["backend"] = args.backend
                    if args.grounded_dir:
                        tool_args["grounded_dir"] = args.grounded_dir
                    res = await session.call_tool("detect", tool_args)
                    return res

        res = asyncio.run(_call_detector())
        res_json = _extract_json_from_call_result(res) or {}
        mask_path = res_json.get("mask_path") or ""
        meta = res_json.get("meta", {})
        if not mask_path:
            raise RuntimeError((res_json.get("error") if isinstance(res_json, dict) else None) or "detector returned empty mask")

        print(json.dumps({"mask_path": mask_path, "meta": meta}, ensure_ascii=False))
        return 0
    except Exception as e:
        print(json.dumps({"mask_path": "", "error": str(e)}), flush=True)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
