#!/usr/bin/env python

"""████
 ██    ██    Datature
   ██  ██    Powering Breakthrough AI
     ██

@File    :   httpx_error_utils.py
@Author  :   Wei Loon Cheng
@Contact :   developers@datature.io
@License :   Apache License 2.0
@Desc    :   Utilities for extracting error messages from httpx exceptions.
"""

import json

import httpx


def extract_error_message_from_httpx_error(error: httpx.HTTPStatusError) -> str:
    """Extract detailed error message from an httpx HTTPStatusError.

    Attempts to extract the most informative error message from an httpx error,
    including server response body content which often contains detailed error
    information (especially for uploads to cloud storage like GCS/S3).

    Args:
        error: The httpx.HTTPStatusError exception.

    Returns:
        A formatted error message string containing:
        - HTTP status code
        - URL that was requested
        - Server error message from response body (if available)
        - Full response text (if JSON parsing fails)

    Example:
        >>> try:
        ...     response.raise_for_status()
        ... except httpx.HTTPStatusError as e:
        ...     error_msg = extract_error_message_from_httpx_error(e)
        ...     print(error_msg)
        HTTP 403 PUT https://storage.googleapis.com/bucket/file
        Server error: Access denied - insufficient permissions

    """
    if not hasattr(error, "response"):
        return str(error)

    response = error.response
    status_code = response.status_code
    method = response.request.method if hasattr(response, "request") else "REQUEST"
    url = str(response.url) if hasattr(response, "url") else "unknown URL"

    # Start with basic error info
    error_parts = [f"HTTP {status_code} {method} {url}"]

    # Try to extract error message from response body
    if hasattr(response, "text") and response.text:
        try:
            # Try parsing as JSON (common for API errors)
            error_data = response.json()

            # Try common error message fields
            server_message = None
            if isinstance(error_data, dict):
                # Check common error message fields
                for field in ["message", "error", "error_description", "detail"]:
                    if field in error_data:
                        server_message = error_data[field]
                        break

                # Check nested error object (e.g., GCS format: {"error": {"message": "..."}})
                if not server_message and "error" in error_data:
                    if isinstance(error_data["error"], dict):
                        server_message = error_data["error"].get(
                            "message", error_data["error"].get("description")
                        )
                    elif isinstance(error_data["error"], str):
                        server_message = error_data["error"]

            if server_message:
                error_parts.append(f"Server error: {server_message}")
            else:
                # Include full JSON if we couldn't extract a specific message
                error_parts.append(f"Server response: {json.dumps(error_data)}")

        except (json.JSONDecodeError, AttributeError, ValueError):
            # Not JSON, include raw text (truncate if very long)
            response_text = response.text[:500]
            if len(response.text) > 500:
                response_text += "... (truncated)"
            error_parts.append(f"Server response: {response_text}")

    return "\n".join(error_parts)
