#!/usr/bin/env python3
"""
Wever Labs hosted rail reference client.

Purpose:
  Give LangChain, CrewAI, OpenClaw, Claude/ChatGPT tool builders, MCP clients,
  and custom agents a ninety-second way to call a hosted Wever Labs rail.

This client does not download or clone the proof spine. It calls hosted Wever Labs
APIs so receipts, verification, work history, and Agent Passport continuity can
stay attached to the hosted run when those artifacts are actually created.

Usage:
  python wever_client.py --base https://weverlabs.com --rail diligenceops-paid-run --agent demo-agent

Optional:
  python wever_client.py --payload sample_payload.json
"""

from __future__ import annotations

import argparse
import json
import sys
import time
import urllib.error
import urllib.request
from typing import Any, Dict, Optional


def post_json(url: str, payload: Dict[str, Any], timeout: int = 30) -> Dict[str, Any]:
    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=data,
        method="POST",
        headers={"Content-Type": "application/json", "Accept": "application/json"},
    )
    try:
        with urllib.request.urlopen(req, timeout=timeout) as res:
            body = res.read().decode("utf-8", errors="replace")
            return {"status": res.status, "body": json.loads(body) if body else {}}
    except urllib.error.HTTPError as exc:
        body = exc.read().decode("utf-8", errors="replace")
        try:
            parsed = json.loads(body)
        except json.JSONDecodeError:
            parsed = {"raw": body}
        return {"status": exc.code, "body": parsed}


def load_payload(path: Optional[str], agent_id: str, rail: str) -> Dict[str, Any]:
    if path:
        with open(path, "r", encoding="utf-8") as f:
            loaded = json.load(f)
        if not isinstance(loaded, dict):
            raise ValueError("Payload file must contain a JSON object.")
        return loaded
    return {
        "agent_id": agent_id,
        "rail_or_product_key": rail,
        "idempotency_key": f"demo-{agent_id}-{int(time.time())}",
        "work_order": {
            "title": "Reference hosted rail call",
            "objective": "Run a free hosted Wever Labs rail and return the response shape.",
            "inputs": {"example": True},
        },
    }


def find_receipt(obj: Any) -> Optional[Dict[str, Any]]:
    if isinstance(obj, dict):
        value = obj.get("receipt")
        if isinstance(value, dict) and isinstance(value.get("receipt_id"), str) and "<" not in value.get("receipt_id", ""):
            return value
        if isinstance(obj.get("receipt_id"), str) and "<" not in obj.get("receipt_id", ""):
            return obj
        for value in obj.values():
            found = find_receipt(value)
            if found:
                return found
    elif isinstance(obj, list):
        for item in obj:
            found = find_receipt(item)
            if found:
                return found
    return None


def main() -> int:
    parser = argparse.ArgumentParser(description="Call a hosted Wever Labs rail.")
    parser.add_argument("--base", default="https://weverlabs.com", help="Base URL for Wever Labs")
    parser.add_argument("--rail", default="diligenceops-paid-run", help="Rail/function key to call")
    parser.add_argument("--agent", default="demo-agent", help="Agent identifier to send")
    parser.add_argument("--payload", help="Optional JSON payload file")
    args = parser.parse_args()

    base = args.base.rstrip("/")
    payload = load_payload(args.payload, args.agent, args.rail)

    print(f"Calling workflow shape: {base}/api/agent-paid-workflow")
    workflow = post_json(f"{base}/api/agent-paid-workflow", {"agent_id": args.agent, "rail_or_product_key": args.rail})
    print(json.dumps(workflow, indent=2))

    print(f"\nCalling hosted rail: {base}/api/{args.rail}")
    run = post_json(f"{base}/api/{args.rail}", payload)
    print(json.dumps(run, indent=2))

    receipt = find_receipt(run.get("body"))
    if receipt:
        receipt_id = receipt.get("receipt_id")
        print(f"\nVerifying receipt: {receipt_id}")
        verification_payload = {
            "mode": "verify_receipt",
            "receipt": receipt,
            "receipt_id": receipt.get("receipt_id"),
            "receipt_hash": receipt.get("receipt_hash"),
            "receipt_signature": receipt.get("receipt_signature"),
            "production_run_id": receipt.get("production_run_id"),
            "return_package_id": receipt.get("return_package_id"),
            "amount_units": receipt.get("total_units") or receipt.get("amount_units"),
            "currency": receipt.get("currency", "usd"),
            "payment_reference": receipt.get("payment_reference"),
            "nonce": receipt.get("nonce"),
            "issued_at": receipt.get("issued_at"),
            "signing_version": receipt.get("signing_version"),
            "rail_key": receipt.get("rail_key"),
            "persist": False,
        }
        verification = post_json(f"{base}/api/receipt-verification", verification_payload)
        print(json.dumps(verification, indent=2))
    else:
        print("\nNo real receipt object found in the run response. This may be expected for shape-only endpoints.")

    return 0 if 200 <= run.get("status", 0) < 500 else 1


if __name__ == "__main__":
    sys.exit(main())
