#!/usr/bin/env python3
"""ReachAgents Public API CLI fallback for Hermes/OpenClaw agents.

Examples:
  reachagents-api GET /v1/whoami
  reachagents-api GET /v1/agents --query workspace_id=...
  reachagents-api POST /v1/contacts --body '{"workspace_id":"...","platform":"x","handle":"example"}' --confirm
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import time
import urllib.parse
import urllib.request
import urllib.error

MUTATING = {"POST", "PATCH", "PUT", "DELETE"}
LIVE_MARKERS = ("/run", "/send", "/cancel", "/bulk")


def env(name: str, default: str = "") -> str:
    return os.environ.get(name, default).rstrip("/")


def public_path(path: str) -> str:
    if not path.startswith("/"):
        path = "/" + path
    if path.startswith("/v1/") or path in {"/agents", "/leads", "/leads/bulk"}:
        return path
    raise SystemExit("Blocked: only ReachAgents Public API /v1/* and legacy public aliases are allowed")


def parse_pairs(values: list[str]) -> dict[str, str]:
    out: dict[str, str] = {}
    for item in values:
        if "=" not in item:
            raise SystemExit(f"Expected key=value, got {item!r}")
        key, value = item.split("=", 1)
        out[key] = value
    return out


def main() -> int:
    parser = argparse.ArgumentParser(description="Call ReachAgents Public API using REACHAGENTS_API_KEY")
    parser.add_argument("method")
    parser.add_argument("path")
    parser.add_argument("--query", action="append", default=[], help="Query pair, e.g. workspace_id=...")
    parser.add_argument("--body", default="", help="JSON body")
    parser.add_argument("--confirm", action="store_true", help="Required for mutating/run/send/bulk/delete calls")
    parser.add_argument("--idempotency-key", default="")
    args = parser.parse_args()

    method = args.method.upper()
    path = public_path(args.path)
    api_base = env("REACHAGENTS_API_BASE_URL", "https://api.reachagents.ai")
    app_url = env("REACHAGENTS_APP_URL", "https://app.reachagents.ai")
    api_key = os.environ.get("REACHAGENTS_API_KEY") or os.environ.get("DES_GROWTH_API_KEY")
    if not api_key:
        print(json.dumps({"ok": False, "error": "missing_api_key", "message": f"Create an API key at {app_url}/settings/api-keys and set REACHAGENTS_API_KEY."}, indent=2))
        return 2

    body = None
    if args.body:
        try:
            body = json.loads(args.body)
        except json.JSONDecodeError as exc:
            raise SystemExit(f"Invalid JSON body: {exc}")

    needs_confirm = method in MUTATING or any(marker in path for marker in LIVE_MARKERS)
    if needs_confirm and not args.confirm:
        print(json.dumps({"ok": False, "error": "approval_required", "message": "Ask the user for explicit approval and retry with --confirm.", "method": method, "path": path}, indent=2))
        return 3

    query = parse_pairs(args.query)
    url = api_base + path
    if query:
        url += "?" + urllib.parse.urlencode(query, doseq=True)
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "Accept": "application/json",
        "X-Request-Id": f"reachagents-cli-{int(time.time()*1000)}",
    }
    if method in MUTATING:
        headers["Idempotency-Key"] = args.idempotency_key or f"reachagents-cli-{int(time.time()*1000)}"
    data = None if body is None else json.dumps(body).encode("utf-8")
    req = urllib.request.Request(url, method=method, headers=headers, data=data)
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            text = resp.read().decode("utf-8")
            payload = json.loads(text) if text else None
            print(json.dumps({"ok": 200 <= resp.status < 300, "status": resp.status, "data": payload}, indent=2))
            return 0 if 200 <= resp.status < 300 else 1
    except urllib.error.HTTPError as exc:
        text = exc.read().decode("utf-8", errors="replace")
        try:
            payload = json.loads(text) if text else None
        except json.JSONDecodeError:
            payload = text
        print(json.dumps({"ok": False, "status": exc.code, "error": payload}, indent=2))
        return 1

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