"""Raw Anthropic API client — models, HTTP call, batch support, response helpers."""

from __future__ import annotations

import json
import time
import urllib.error
import urllib.request
from typing import Any

HAIKU  = "claude-haiku-4-5-20251001"
SONNET = "claude-sonnet-4-6"

_API_BASE    = "https://api.anthropic.com/v1"
_API_URL     = f"{_API_BASE}/messages"
_BATCH_URL   = f"{_API_BASE}/messages/batches"
_API_VERSION = "2023-06-01"


def _headers(api_key: str, *, beta: str | None = None) -> dict[str, str]:
    h: dict[str, str] = {
        "Content-Type":      "application/json",
        "x-api-key":         api_key,
        "anthropic-version": _API_VERSION,
    }
    if beta:
        h["anthropic-beta"] = beta
    return h


def call(
    model: str,
    messages: list[dict],
    *,
    api_key: str,
    tools: list[dict] | None = None,
    output_config: dict | None = None,
    max_tokens: int = 1024,
    system: str | None = None,
) -> dict:
    payload: dict[str, Any] = {
        "model":      model,
        "max_tokens": max_tokens,
        "messages":   messages,
    }
    if system:        payload["system"]        = system
    if tools:         payload["tools"]         = tools
    if output_config: payload["output_config"] = output_config

    beta = None
    if tools and any(t.get("type", "").startswith("web_search") for t in tools):
        beta = "web-search-2025-03-05"

    data = json.dumps(payload).encode()
    req  = urllib.request.Request(_API_URL, data=data, headers=_headers(api_key, beta=beta), method="POST")
    try:
        with urllib.request.urlopen(req, timeout=90) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as exc:
        try:
            return {"error": json.loads(exc.read())}
        except Exception:
            return {"error": str(exc)}
    except Exception as exc:
        return {"error": str(exc)}


# ── Message Batches (50% cost reduction) ──────────────────────────────────────

def _api_request(method: str, url: str, api_key: str, body: dict | None = None, beta: str | None = None) -> dict:
    data = json.dumps(body).encode() if body else None
    req = urllib.request.Request(url, data=data, headers=_headers(api_key, beta=beta), method=method)
    try:
        with urllib.request.urlopen(req, timeout=90) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as exc:
        try:
            return {"error": json.loads(exc.read()), "status": exc.code}
        except Exception:
            return {"error": str(exc), "status": exc.code}
    except Exception as exc:
        return {"error": str(exc)}


def create_batch(
    requests: list[dict],
    *,
    api_key: str,
) -> dict:
    """Submit a message batch. Each request: {custom_id, params: {model, messages, ...}}."""
    return _api_request("POST", _BATCH_URL, api_key, body={"requests": requests})


def poll_batch(batch_id: str, *, api_key: str, poll_interval: int = 10, timeout: int = 600) -> dict:
    """Poll a batch until it completes. Returns the batch object."""
    deadline = time.time() + timeout
    while time.time() < deadline:
        result = _api_request("GET", f"{_BATCH_URL}/{batch_id}", api_key)
        status = result.get("processing_status")
        if status == "ended":
            return result
        if result.get("error"):
            return result
        time.sleep(poll_interval)
    return {"error": "batch timed out"}


def get_batch_results(results_url: str, *, api_key: str) -> dict[str, dict]:
    """Fetch batch results. Returns {custom_id: response_dict}."""
    req = urllib.request.Request(results_url, headers=_headers(api_key), method="GET")
    out: dict[str, dict] = {}
    try:
        with urllib.request.urlopen(req, timeout=90) as resp:
            for line in resp.read().decode().strip().split("\n"):
                if not line.strip():
                    continue
                entry = json.loads(line)
                cid = entry.get("custom_id", "")
                if entry.get("result", {}).get("type") == "succeeded":
                    out[cid] = entry["result"]["message"]
    except Exception:
        pass
    return out


def text_from(response: dict) -> str:
    """Concatenate all text blocks from an Anthropic response."""
    return "\n".join(
        b.get("text", "") for b in response.get("content", []) if b.get("type") == "text"
    )


