from __future__ import annotations

import os
from typing import Any

import httpx

from .contract import ProviderCapabilities, ProviderFeatures, ProviderLimits
from .errors import ProviderError
from ..ports.execution_port import NormalizedResponse


def get_capabilities() -> ProviderCapabilities:
    return ProviderCapabilities(
        provider_id="anthropic",
        features=ProviderFeatures(streaming=False, tools=False, json_mode=False),
        limits=ProviderLimits(
            max_output_tokens=8192,
            default_max_tokens=256,
            timeout_seconds=60.0,
        ),
        requires_api_key=True,
        execution_mode="http",
    )


def _max_tokens(default: int) -> int:
    raw = os.getenv("ANTHROPIC_MAX_TOKENS", "").strip()
    if not raw:
        return default
    try:
        value = int(raw)
    except ValueError:
        return default
    return value if value > 0 else default


def execute(*, model_id: str, messages: list[dict[str, str]], api_key: str | None = None, max_tokens: int | None = None, **_: Any) -> NormalizedResponse:
    key = (api_key or os.getenv("ANTHROPIC_API_KEY", "")).strip()
    if not key:
        raise ProviderError("missing Anthropic credentials")

    last_user = next((m["content"] for m in reversed(messages) if m.get("role") == "user"), None)
    if not last_user:
        raise ProviderError("no user message")

    effective_max_tokens = max_tokens if max_tokens is not None else _max_tokens(256)
    headers = {"x-api-key": key, "anthropic-version": "2023-06-01", "content-type": "application/json"}
    payload: dict[str, Any] = {
        "model": model_id,
        "max_tokens": effective_max_tokens,
        "messages": [{"role": "user", "content": [{"type": "text", "text": last_user}]}],
        "temperature": 0.2,
    }

    with httpx.Client(timeout=60.0) as client:
        try:
            resp = client.post("https://api.anthropic.com/v1/messages", json=payload, headers=headers)
        except httpx.RequestError as exc:
             raise ProviderError(f"connection error: {str(exc)}") from exc

        if resp.status_code >= 400:
            try:
                data = resp.json()
            except Exception:
                data = {}
            msg = data.get("error", {}).get("message") or f"HTTP {resp.status_code}"
            err = ProviderError(msg)
            err.status_code = resp.status_code
            err.code = data.get("error", {}).get("type")
            raise err

        data = resp.json()
        blocks = data.get("content", [])
        text = "".join([b.get("text", "") for b in blocks if b.get("type") == "text"])
        tool_calls: list[dict[str, Any]] = []
        for b in blocks:
            if b.get("type") == "tool_use":
                tool_calls.append({
                    "tool_name": b.get("name", ""),
                    "arguments": b.get("input", {}),
                })
        return NormalizedResponse(text=str(text or ""), tool_calls=tool_calls)
