"""
Centralized Exception Handler
Wraps all exceptions in unified format
"""
import logging
from rest_framework.views import exception_handler
from rest_framework import status
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from .response import get_request_id, error_response

logger = logging.getLogger(__name__)


def custom_exception_handler(exc, context):
    """
    Custom exception handler that wraps all errors in unified format
    
    Args:
        exc: The exception that was raised
        context: Dictionary containing request, view, args, kwargs
    
    Returns:
        Response object with unified error format
    """
    # Get request from context
    request = context.get('request')
    
    # Get request ID
    request_id = get_request_id(request) if request else None
    
    # Call DRF's default exception handler first
    response = exception_handler(exc, context)
    
    # If DRF handled it, wrap it in unified format
    if response is not None:
        # Extract error details from DRF response
        error_message = None
        errors = None
        status_code = response.status_code
        
        # Try to extract error message from response data
        if hasattr(response, 'data'):
            if isinstance(response.data, dict):
                # DRF validation errors
                if 'detail' in response.data:
                    error_message = str(response.data['detail'])
                elif 'non_field_errors' in response.data:
                    error_message = str(response.data['non_field_errors'][0]) if response.data['non_field_errors'] else None
                    errors = response.data
                else:
                    # Field-specific errors
                    errors = response.data
                    # Create top-level error message
                    if errors:
                        first_error = list(errors.values())[0] if errors else None
                        if first_error and isinstance(first_error, list) and len(first_error) > 0:
                            error_message = str(first_error[0])
                        elif first_error:
                            error_message = str(first_error)
                        else:
                            error_message = 'Validation failed'
            elif isinstance(response.data, list):
                # List of errors
                error_message = str(response.data[0]) if response.data else 'Validation failed'
            else:
                error_message = str(response.data)
        
        # Map status codes to appropriate error messages
        if not error_message:
            if status_code == status.HTTP_400_BAD_REQUEST:
                error_message = 'Bad request'
            elif status_code == status.HTTP_401_UNAUTHORIZED:
                error_message = 'Authentication required'
            elif status_code == status.HTTP_403_FORBIDDEN:
                error_message = 'Permission denied'
            elif status_code == status.HTTP_404_NOT_FOUND:
                error_message = 'Resource not found'
            elif status_code == status.HTTP_409_CONFLICT:
                error_message = 'Conflict'
            elif status_code == status.HTTP_422_UNPROCESSABLE_ENTITY:
                error_message = 'Validation failed'
            elif status_code == status.HTTP_429_TOO_MANY_REQUESTS:
                error_message = 'Rate limit exceeded'
            elif status_code >= 500:
                error_message = 'Internal server error'
            else:
                error_message = 'An error occurred'
        
        # Prepare debug info (only in DEBUG mode)
        debug_info = None
        if settings.DEBUG:
            debug_info = {
                'exception_type': type(exc).__name__,
                'exception_message': str(exc),
                'view': context.get('view').__class__.__name__ if context.get('view') else None,
                'path': request.path if request else None,
                'method': request.method if request else None,
            }
            # Include traceback in debug mode
            import traceback
            debug_info['traceback'] = traceback.format_exc()
        
        # Log the error
        if status_code >= 500:
            logger.error(
                f"Server error: {error_message}",
                extra={
                    'request_id': request_id,
                    'endpoint': request.path if request else None,
                    'method': request.method if request else None,
                    'user_id': request.user.id if request and request.user and request.user.is_authenticated else None,
                    'account_id': request.account.id if request and hasattr(request, 'account') and request.account else None,
                    'status_code': status_code,
                    'exception_type': type(exc).__name__,
                },
                exc_info=True
            )
        elif status_code >= 400:
            logger.warning(
                f"Client error: {error_message}",
                extra={
                    'request_id': request_id,
                    'endpoint': request.path if request else None,
                    'method': request.method if request else None,
                    'user_id': request.user.id if request and request.user and request.user.is_authenticated else None,
                    'account_id': request.account.id if request and hasattr(request, 'account') and request.account else None,
                    'status_code': status_code,
                }
            )
        
        # Return unified error response
        return error_response(
            error=error_message,
            errors=errors,
            status_code=status_code,
            request=request,
            debug_info=debug_info
        )
    
    # If DRF didn't handle it, it's an unhandled exception
    # Log it and return unified error response
    logger.error(
        f"Unhandled exception: {type(exc).__name__}: {str(exc)}",
        extra={
            'request_id': request_id,
            'endpoint': request.path if request else None,
            'method': request.method if request else None,
            'user_id': request.user.id if request and request.user and request.user.is_authenticated else None,
            'account_id': request.account.id if request and hasattr(request, 'account') and request.account else None,
        },
        exc_info=True
    )
    
    # Prepare debug info
    debug_info = None
    if settings.DEBUG:
        import traceback
        debug_info = {
            'exception_type': type(exc).__name__,
            'exception_message': str(exc),
            'view': context.get('view').__class__.__name__ if context.get('view') else None,
            'path': request.path if request else None,
            'method': request.method if request else None,
            'traceback': traceback.format_exc()
        }
    
    return error_response(
        error='Internal server error',
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        request=request,
        debug_info=debug_info
    )


