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

from __future__ import annotations

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

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

_API_URL     = "https://api.anthropic.com/v1/messages"
_API_VERSION = "2023-06-01"


def call(
    model: str,
    messages: list[dict],
    *,
    api_key: str,
    tools: list[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

    headers: dict[str, str] = {
        "Content-Type":      "application/json",
        "x-api-key":         api_key,
        "anthropic-version": _API_VERSION,
    }
    if tools and any(t.get("type", "").startswith("web_search") for t in tools):
        headers["anthropic-beta"] = "web-search-2025-03-05"

    data = json.dumps(payload).encode()
    req  = urllib.request.Request(_API_URL, data=data, headers=headers, 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)}


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"
    )


def parse_json(text: str) -> dict | None:
    """Parse JSON from a response that may be wrapped in markdown fences."""
    text = text.strip()
    if text.startswith("```"):
        parts = text.split("```")
        if len(parts) >= 2:
            text = parts[1]
            if text.startswith("json"):
                text = text[4:]
    try:
        return json.loads(text.strip())
    except json.JSONDecodeError:
        pass
    m = re.search(r"\{.*\}", text, re.DOTALL)
    if m:
        try:
            return json.loads(m.group())
        except Exception:
            pass
    return None
