import logging
from typing import Dict, Any

from django.http import Http404
from rest_framework.views import exception_handler
from rest_framework.response import Response

from drf_standardized_responses.responses import StandardResponse

# Configure a logger for the module
logger = logging.getLogger(__name__)


def standardized_exception_handler(exc: Exception, context: Dict[str, Any]) -> Response:
    """
    Django REST Framework exception handler that standardizes API error responses.

    This handler wraps DRF's default exception handling to ensure all API errors
    follow a consistent response structure. It extracts relevant information from
    exceptions and formats them according to the project's response standards.

    Args:
        exc: The exception instance raised during request processing.
        context: A dictionary containing contextual information about the request.

    Returns:
        Response: A standardized API error response with appropriate status code
                 and error details.

    Example:
        To use this handler, add the following to your Django settings:

        REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'drf_standardized_responses.exceptions.standardized_exception_handler',
            # other settings...
        }
    """
    # Initialize errors variable to None by default
    errors = None

    # Call Django REST Framework's default exception handler to get the initial response
    response = exception_handler(exc, context)

    if response is not None:
        # Extract the 'detail' attribute from the exception, if available
        detail = getattr(exc, 'detail', None)

        # Special handling for Http404 exceptions - retain their original message
        if isinstance(exc, Http404):
            message = str(exc)
        # Check if the detail is a list or dictionary (e.g., validation errors)
        elif isinstance(detail, (list, dict)):
            # Use a specific message for validation errors, otherwise a generic one
            message = "Validation failed" if response.status_code == 400 else "Request failed"
            errors = detail  # Include the detailed errors
        else:
            # Handle other types of errors with a generic message
            message = str(detail) if detail else "Request failed"

        # Return a standardized error response with the extracted details
        return StandardResponse.error(
            message=message,
            status_code=response.status_code,
            errors=errors
        )

    # Log the unhandled exception for debugging
    logger.error("Internal server error occurred", exc_info=exc)

    # If no response is generated by the default handler, return a generic 500 error
    return StandardResponse.error(
        message="Internal server error",
        status_code=500
    )