"""Thin wrapper over httpx for ACL API calls with unified error handling."""

from __future__ import annotations

import httpx
import typer

from acl_cli import config
from acl_cli.output import error, warning


class ACLAPIError(Exception):
    """Raised when ACL API returns an error."""


def _api_key() -> str:
    key = config.get_api_key()
    if not key:
        error("Конфигурация не найдена. Сначала запустите: acl init")
        raise typer.Exit(1)
    return key


def make_client() -> httpx.Client:
    return httpx.Client(
        base_url=config.get_base_url(),
        headers={"Authorization": f"Bearer {_api_key()}"},
        timeout=30.0,
    )


def _handle_response_error(exc: httpx.HTTPStatusError) -> None:
    """Handle HTTP errors with user-friendly messages."""
    status = exc.response.status_code

    if status == 429:
        warning("Слишком много запросов. Подождите немного и повторите.")
        raise typer.Exit(1)

    if status == 401:
        error("Неверный API-ключ. Перенастройте: acl init --reset")
        raise typer.Exit(1)

    if status == 404:
        error(f"Ресурс не найден: {exc.request.url.path}")
        raise typer.Exit(1)

    # Try to extract detail from JSON body
    detail = exc.response.text
    ct = exc.response.headers.get("content-type", "")
    if ct.startswith("application/json"):
        try:
            body = exc.response.json()
            detail = body.get("detail", detail)
        except Exception:
            pass

    error(f"Ошибка API ({status}): {detail}")
    raise typer.Exit(1)


def _handle_connection_error(exc: httpx.RequestError) -> None:
    """Handle connection errors with user-friendly messages."""
    base_url = config.get_base_url()
    error(f"ACL API недоступен: {base_url}")
    error(f"Проверьте соединение или статус сервера.")
    raise typer.Exit(1)


def post(path: str, json: dict | None = None, headers: dict | None = None) -> dict:
    with make_client() as c:
        h = headers or {}
        try:
            resp = c.post(path, json=json, headers=h)
            resp.raise_for_status()
            return resp.json()
        except httpx.HTTPStatusError as exc:
            _handle_response_error(exc)
        except httpx.RequestError as exc:
            _handle_connection_error(exc)
    return {}  # unreachable, satisfies type checker


def get(path: str, params: dict | None = None, headers: dict | None = None) -> dict | list:
    with make_client() as c:
        h = headers or {}
        try:
            resp = c.get(path, params=params, headers=h)
            resp.raise_for_status()
            return resp.json()
        except httpx.HTTPStatusError as exc:
            _handle_response_error(exc)
        except httpx.RequestError as exc:
            _handle_connection_error(exc)
    return {}


def delete(path: str, headers: dict | None = None) -> None:
    with make_client() as c:
        h = headers or {}
        try:
            resp = c.delete(path, headers=h)
            resp.raise_for_status()
        except httpx.HTTPStatusError as exc:
            _handle_response_error(exc)
        except httpx.RequestError as exc:
            _handle_connection_error(exc)
