from __future__ import annotations

"""Base resource class for SDK HTTP operations."""

from typing import Any

import httpx

from nexure.exceptions import NexureConnectionError, NexureTimeoutError, _handle_response


def _wrap_transport_error(exc: httpx.HTTPError) -> NexureConnectionError | NexureTimeoutError:
    """Convert httpx transport exceptions into Nexure SDK exceptions."""
    base_url = str(exc.request.url.host) if hasattr(exc, "request") and exc.request else "unknown"
    if isinstance(exc, httpx.TimeoutException):
        return NexureTimeoutError(
            f"Request timed out connecting to {base_url}. "
            "Try increasing the timeout parameter or check your network connection."
        )
    return NexureConnectionError(
        f"Could not reach the Nexure API at {base_url}. "
        "Check your network connection or base_url configuration."
    )


class BaseResource:
    """Base class for all SDK resource namespaces."""

    def __init__(self, client: httpx.Client):
        self._client = client

    def _get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        """Send a GET request and return parsed JSON."""
        try:
            resp = self._client.get(path, params=params)
        except httpx.HTTPError as exc:
            raise _wrap_transport_error(exc) from exc
        body = resp.json()
        _handle_response(resp.status_code, body, dict(resp.headers))
        return body

    def _post(self, path: str, json: dict[str, Any] | None = None) -> dict[str, Any]:
        """Send a POST request and return parsed JSON."""
        try:
            resp = self._client.post(path, json=json)
        except httpx.HTTPError as exc:
            raise _wrap_transport_error(exc) from exc
        body = resp.json()
        _handle_response(resp.status_code, body, dict(resp.headers))
        return body

    def _put(self, path: str, json: dict[str, Any] | None = None) -> dict[str, Any]:
        """Send a PUT request and return parsed JSON."""
        try:
            resp = self._client.put(path, json=json)
        except httpx.HTTPError as exc:
            raise _wrap_transport_error(exc) from exc
        body = resp.json()
        _handle_response(resp.status_code, body, dict(resp.headers))
        return body

    def _patch(self, path: str, json: dict[str, Any] | None = None) -> dict[str, Any]:
        """Send a PATCH request and return parsed JSON."""
        try:
            resp = self._client.patch(path, json=json)
        except httpx.HTTPError as exc:
            raise _wrap_transport_error(exc) from exc
        body = resp.json()
        _handle_response(resp.status_code, body, dict(resp.headers))
        return body

    def _delete(self, path: str) -> None:
        """Send a DELETE request (expects 204 No Content)."""
        try:
            resp = self._client.delete(path)
        except httpx.HTTPError as exc:
            raise _wrap_transport_error(exc) from exc
        if resp.status_code >= 400:
            body = resp.json() if resp.content else {}
            _handle_response(resp.status_code, body, dict(resp.headers))
