from rest_framework.views import exception_handler
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework import status
from django.utils.timezone import now
from django.http import Http404
from django.core.exceptions import PermissionDenied
from django.conf import settings
import datetime
import logging
import traceback


def custom_exception_handler(exc, context):
    """
    Enhanced custom exception handler that ensures JSON responses for all errors.
    """
    logger = logging.getLogger(__name__)
    
    # Call REST framework's default exception handler first
    response = exception_handler(exc, context)

    if response is not None:
        # DRF handled the exception, customize the response format
        status_code = response.status_code
        message = "Something went wrong."
        raw_errors = response.data

        # Format timestamp (ISO 8601 with timezone)
        timestamp = datetime.datetime.now().astimezone().isoformat()

        # Customize message by exception type
        if isinstance(exc, ValidationError):
            message = "Validation failed."
        elif isinstance(exc, Http404):
            message = "Resource not found."
        elif isinstance(exc, PermissionDenied):
            message = "You do not have permission to perform this action."
        elif status_code == 500:
            message = "Internal server error."

        # Preserve original error structure for ValidationErrors (like storage capacity errors)
        if isinstance(exc, ValidationError) and isinstance(raw_errors, dict):
            # Keep the original structure for detailed error messages
            response.data = raw_errors
            # Add metadata if needed
            if "storage_info" not in raw_errors and "error" not in raw_errors:
                response.data["timestamp"] = timestamp
                response.data["status"] = status_code
        else:
            # Flatten errors to a list for other error types
            if isinstance(raw_errors, dict):
                errors = []
                for field, detail in raw_errors.items():
                    if isinstance(detail, list):
                        errors.extend(detail)
                    else:
                        errors.append(str(detail))
            elif isinstance(raw_errors, list):
                errors = raw_errors
            else:
                errors = [str(raw_errors)]

            # Final structured response
            response.data = {
                "timestamp": timestamp,
                "status": status_code,
                "message": message,
                "errors": errors
            }

        return response
    
    # Handle unhandled exceptions (this is the key fix for empty response bodies)
    logger.error(f"Unhandled exception: {str(exc)}", exc_info=True)
    
    # Create a JSON error response for unhandled exceptions
    error_response = {
        "timestamp": datetime.datetime.now().astimezone().isoformat(),
        "status": 500,
        "error": "An internal server error occurred.",
        "type": exc.__class__.__name__
    }
    
    # Add detailed error info in debug mode
    if settings.DEBUG:
        error_response["detail"] = str(exc)
        error_response["traceback"] = traceback.format_exc()
    
    return Response(error_response, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
