"""A reconnecting HTTP MCP client using Python's standard library.

Session identity and protocol are persisted; every request has a fresh ID.
The client never silently initializes a replacement for an expired session.
"""
import argparse
import json
from pathlib import Path
import secrets
import urllib.error
import urllib.request
import uuid

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=["setup", "connect", "quote", "discount", "trust", "revoke"])
parser.add_argument("sku", nargs="?", default="sku-118")
parser.add_argument("percent", nargs="?", type=float, default=10.0)
args = parser.parse_args()
directory = Path("state/mcp")
directory.mkdir(mode=0o700, parents=True, exist_ok=True)
token_file = directory / "auth-token.txt"
session_file = directory / "client-session.json"

def write_private(path, value):
    import os
    fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
    with os.fdopen(fd, "w") as target:
        target.write(value)

if args.action == "setup":
    if not token_file.exists():
        write_private(token_file, secrets.token_hex(32))
    print("Ready: state/mcp. Credential: state/mcp/auth-token.txt")
    raise SystemExit(0)

token = token_file.read_text().strip()
session = None if args.action == "connect" else json.loads(session_file.read_text())

def send(method, params=None, notification=False, path="/mcp", verb="POST"):
    request_id = str(uuid.uuid4())
    body = {"jsonrpc": "2.0", "method": method, "params": params or {}}
    if not notification:
        body["id"] = request_id
    headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept": "application/json, text/event-stream", "MCP-Protocol-Version": "2025-11-25"}
    if session:
        headers.update({"MCP-Session-Id": session["id"], "MCP-Protocol-Version": session["protocol"]})
    request = urllib.request.Request("http://127.0.0.1:4313" + path, data=json.dumps(body).encode() if verb == "POST" else None, headers=headers, method=verb)
    try:
        with urllib.request.urlopen(request, timeout=15) as response:
            if response.status == 202:
                return {}, dict(response.headers)
            if "text/event-stream" in response.headers.get("Content-Type", ""):
                for raw in response:
                    if raw.startswith(b"data:"):
                        event = json.loads(raw[5:].strip())
                        if event.get("id") == request_id:
                            return event, dict(response.headers)
                raise RuntimeError("The event stream ended without this request's result")
            return json.load(response), dict(response.headers)
    except urllib.error.HTTPError as error:
        raise SystemExit(f"HTTP {error.code}: {error.read().decode()}\nThe client has kept its session file. Inspect expiry, credentials, policy, or revocation before reconnecting.") from error

if args.action == "connect":
    if session_file.exists():
        raise SystemExit("A saved session already exists. Use quote or discount to reconnect. Archive the file explicitly before establishing new authority.")
    result, headers = send("initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "larkfield-pricing-client", "version": "1.0.0"}})
    if "result" not in result:
        raise SystemExit(json.dumps(result, indent=2))
    session_id = next(value for name, value in headers.items() if name.lower() == "mcp-session-id")
    session = {"id": session_id, "protocol": result["result"]["protocolVersion"]}
    send("notifications/initialized", notification=True)
    write_private(session_file, json.dumps(session, indent=2))
    print("Connected. Saved session:", session["id"])
elif args.action in {"trust", "revoke"}:
    result, _ = send("", path=f"/admin/sessions/{session['id']}/trust", verb="GET" if args.action == "trust" else "POST")
    print(json.dumps(result, indent=2))
else:
    result, _ = send("tools/call", {"name": args.action, "arguments": {"sku": args.sku, "percent": args.percent}})
    print(json.dumps(result, indent=2))
    if "error" in result or result.get("result", {}).get("isError"):
        raise SystemExit(1)
