"""
Custom exception handlers for the API.
"""
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.core.exceptions import ValidationError
from django.db import IntegrityError
import logging

logger = logging.getLogger(__name__)


def custom_exception_handler(exc, context):
    """
    Custom exception handler for API responses.
    """
    # Call REST framework's default exception handler first
    response = exception_handler(exc, context)
    
    if response is not None:
        custom_response_data = {
            'error': True,
            'message': 'An error occurred',
            'details': response.data,
            'status_code': response.status_code,
        }
        
        # Handle specific error types
        if isinstance(exc, ValidationError):
            custom_response_data['message'] = 'Validation error'
            custom_response_data['details'] = exc.message_dict if hasattr(exc, 'message_dict') else str(exc)
            
        elif isinstance(exc, IntegrityError):
            custom_response_data['message'] = 'Data integrity error'
            custom_response_data['details'] = 'The operation could not be completed due to data constraints'
            response.status_code = status.HTTP_400_BAD_REQUEST
            
        elif response.status_code == status.HTTP_401_UNAUTHORIZED:
            custom_response_data['message'] = 'Authentication required'
            custom_response_data['details'] = 'Please provide valid authentication credentials'
            
        elif response.status_code == status.HTTP_403_FORBIDDEN:
            custom_response_data['message'] = 'Access denied'
            custom_response_data['details'] = 'You do not have permission to perform this action'
            
        elif response.status_code == status.HTTP_404_NOT_FOUND:
            custom_response_data['message'] = 'Resource not found'
            custom_response_data['details'] = 'The requested resource could not be found'
            
        elif response.status_code == status.HTTP_429_TOO_MANY_REQUESTS:
            custom_response_data['message'] = 'Rate limit exceeded'
            custom_response_data['details'] = 'Too many requests. Please try again later.'
            
        elif response.status_code >= 500:
            custom_response_data['message'] = 'Internal server error'
            custom_response_data['details'] = 'An unexpected error occurred. Please try again later.'
            # Log server errors
            logger.error(f"Server error: {exc}", exc_info=True)
        
        response.data = custom_response_data
    
    return response


class APIException(Exception):
    """
    Base exception for API errors.
    """
    status_code = status.HTTP_400_BAD_REQUEST
    message = 'An error occurred'
    
    def __init__(self, message=None, status_code=None, details=None):
        if message:
            self.message = message
        if status_code:
            self.status_code = status_code
        self.details = details or {}
        super().__init__(self.message)


class ValidationException(APIException):
    """
    Exception for validation errors.
    """
    status_code = status.HTTP_400_BAD_REQUEST
    message = 'Validation error'


class AuthenticationException(APIException):
    """
    Exception for authentication errors.
    """
    status_code = status.HTTP_401_UNAUTHORIZED
    message = 'Authentication required'


class PermissionException(APIException):
    """
    Exception for permission errors.
    """
    status_code = status.HTTP_403_FORBIDDEN
    message = 'Access denied'


class NotFoundException(APIException):
    """
    Exception for not found errors.
    """
    status_code = status.HTTP_404_NOT_FOUND
    message = 'Resource not found'


class RateLimitException(APIException):
    """
    Exception for rate limit errors.
    """
    status_code = status.HTTP_429_TOO_MANY_REQUESTS
    message = 'Rate limit exceeded'


class BusinessLogicException(APIException):
    """
    Exception for business logic errors.
    """
    status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
    message = 'Business logic error'

