"""Prove ccr forwards tools to a bare OpenAI-compatible provider and accepts a
synthesized tool_calls reply.

This is the one layer the sol-web design owns neither side of: Claude Code speaks
Anthropic, solwebd speaks OpenAI, and ccr translates between them. Find a failure
here with a stub, not with a real ChatGPT turn.

Run: python3 modules/gptbridge/tests/ccr_passthrough_probe.py
"""

from __future__ import annotations

import json
import os
import shutil
import subprocess
import sys
import threading
import time
import urllib.error
import urllib.request
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path

STATE = Path.home() / ".overdeck" / "gptbridge"
TMP = STATE / "tmp"
CCR_CONFIG = Path.home() / ".claude-code-router" / "config.json"
CCR_UP = Path.home() / ".claude" / "workflows" / "lib" / "ccr-up.sh"
PROVIDER = "solweb-probe"
PORT = 8791
TOKEN = "probe-token"
MODELS = [f"sol-web-{e}" for e in ("instant", "medium", "high", "xhigh", "pro")]

received: list[dict] = []


class Stub(BaseHTTPRequestHandler):
    def log_message(self, *args):  # keep the probe's output clean
        pass

    def _json(self, status: int, payload: dict) -> None:
        body = json.dumps(payload).encode()
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _authed(self) -> bool:
        if self.headers.get("Authorization") == f"Bearer {TOKEN}":
            return True
        self._json(401, {"error": "unauthorized"})
        return False

    def do_GET(self):
        if not self._authed():
            return
        if self.path.rstrip("/").endswith("/models"):
            self._json(200, {"data": [{"id": m, "object": "model"} for m in MODELS]})
        else:
            self._json(404, {"error": "not found"})

    def do_POST(self):
        if not self._authed():
            return
        raw = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        body = json.loads(raw or b"{}")
        received.append(body)
        (TMP / f"ccr-probe-{len(received)}.json").write_text(json.dumps(body, indent=1))
        tools = body.get("tools") or []
        name = "unknown"
        if tools:
            first = tools[0]
            name = first.get("function", {}).get("name") or first.get("name") or "unknown"
        self._json(200, {
            "id": "chatcmpl-probe", "object": "chat.completion", "created": 0,
            "model": body.get("model", ""),
            "choices": [{"index": 0, "finish_reason": "tool_calls", "message": {
                "role": "assistant", "content": None,
                "tool_calls": [{"id": "call_0_deadbeef", "type": "function", "function": {
                    "name": name, "arguments": json.dumps({"command": "ls"})}}]}}],
            "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2},
        })


def edit_ccr_config(add: bool) -> None:
    config = json.loads(CCR_CONFIG.read_text())
    config["Providers"] = [p for p in config.get("Providers", []) if p.get("name") != PROVIDER]
    if add:
        config["Providers"].append({
            "name": PROVIDER,
            "api_base_url": f"http://127.0.0.1:{PORT}/v1/chat/completions",
            "api_key": TOKEN,
            "models": MODELS,
        })
    CCR_CONFIG.write_text(json.dumps(config, indent=2))


def ccr_up() -> dict:
    out = subprocess.run(["bash", str(CCR_UP), "solweb-probe"],
                         capture_output=True, text=True, timeout=120).stdout.strip()
    return json.loads(out.splitlines()[-1]) if out else {"up": False, "detail": "no output"}


def ccr_restart() -> None:
    """ccr caches its config at start, so a new provider needs a restart."""
    if shutil.which("ccr"):
        subprocess.run(["ccr", "stop"], capture_output=True, text=True, timeout=60)
        time.sleep(2)


def anthropic_request() -> dict:
    payload = {
        "model": f"{PROVIDER},sol-web-medium",
        "max_tokens": 256,
        "system": "be terse",
        "messages": [{"role": "user", "content": "count the py files here"}],
        "tools": [{"name": "run_command", "description": "run a shell command",
                   "input_schema": {"type": "object",
                                    "properties": {"command": {"type": "string"}},
                                    "required": ["command"]}}],
    }
    config = json.loads(CCR_CONFIG.read_text())
    request = urllib.request.Request(
        f"http://127.0.0.1:{config.get('PORT', 3456)}/v1/messages",
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json",
                 "x-api-key": config.get("APIKEY", ""),
                 "anthropic-version": "2023-06-01"},
    )
    with urllib.request.urlopen(request, timeout=120) as response:
        return json.loads(response.read())


def main() -> int:
    TMP.mkdir(parents=True, exist_ok=True)
    for stale in TMP.glob("ccr-probe-*.json"):
        stale.unlink()
    backup = CCR_CONFIG.with_suffix(".json.probe-backup")
    shutil.copy2(CCR_CONFIG, backup)

    server = HTTPServer(("127.0.0.1", PORT), Stub)
    threading.Thread(target=server.serve_forever, daemon=True).start()
    try:
        edit_ccr_config(add=True)
        ccr_restart()
        state = ccr_up()
        if not state.get("up"):
            print(f"FAIL ccr did not come up: {state.get('detail')}")
            return 3
        try:
            reply = anthropic_request()
        except urllib.error.HTTPError as exc:
            print(f"FAIL ccr returned HTTP {exc.code}: {exc.read().decode()[:400]}")
            return 1
        if not received:
            print("FAIL ccr never reached the provider")
            return 1
        forwarded = received[0].get("tools") or []
        blocks = reply.get("content") or []
        accepted = any(b.get("type") == "tool_use" for b in blocks if isinstance(b, dict))
        print(f"PASS tools_forwarded={len(forwarded)} tool_calls_accepted={str(accepted).lower()}")
        if not forwarded or not accepted:
            print("  request tools:", json.dumps(forwarded)[:300])
            print("  reply:", json.dumps(reply)[:500])
            return 1
        return 0
    finally:
        server.shutdown()
        shutil.copy2(backup, CCR_CONFIG)
        backup.unlink()
        ccr_restart()


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