"""
Standardized Error Response Utilities
Ensures consistent error formats across the billing module
"""
from rest_framework import status
from rest_framework.response import Response
from typing import Dict, Any, Optional, List


class ErrorCode:
    """Standardized error codes for billing module"""
    # Payment errors
    PAYMENT_NOT_FOUND = 'payment_not_found'
    PAYMENT_ALREADY_PROCESSED = 'payment_already_processed'
    PAYMENT_AMOUNT_MISMATCH = 'payment_amount_mismatch'
    PAYMENT_METHOD_NOT_AVAILABLE = 'payment_method_not_available'
    
    # Invoice errors
    INVOICE_NOT_FOUND = 'invoice_not_found'
    INVOICE_ALREADY_PAID = 'invoice_already_paid'
    INVOICE_VOIDED = 'invoice_voided'
    INVOICE_EXPIRED = 'invoice_expired'
    
    # Subscription errors
    SUBSCRIPTION_NOT_FOUND = 'subscription_not_found'
    SUBSCRIPTION_INACTIVE = 'subscription_inactive'
    SUBSCRIPTION_ALREADY_EXISTS = 'subscription_already_exists'
    
    # Credit errors
    INSUFFICIENT_CREDITS = 'insufficient_credits'
    INVALID_CREDIT_PACKAGE = 'invalid_credit_package'
    
    # Validation errors
    VALIDATION_ERROR = 'validation_error'
    MISSING_REQUIRED_FIELD = 'missing_required_field'
    INVALID_STATUS_TRANSITION = 'invalid_status_transition'
    
    # Authorization errors
    UNAUTHORIZED = 'unauthorized'
    FORBIDDEN = 'forbidden'
    
    # System errors
    INTERNAL_ERROR = 'internal_error'
    TIMEOUT = 'timeout'
    RATE_LIMITED = 'rate_limited'


def error_response(
    message: str,
    code: str = ErrorCode.INTERNAL_ERROR,
    details: Optional[Dict[str, Any]] = None,
    field_errors: Optional[Dict[str, List[str]]] = None,
    status_code: int = status.HTTP_400_BAD_REQUEST
) -> Response:
    """
    Create standardized error response
    
    Args:
        message: Human-readable error message
        code: Error code from ErrorCode class
        details: Additional error context
        field_errors: Field-specific validation errors
        status_code: HTTP status code
        
    Returns:
        DRF Response with standardized error format
    """
    response_data = {
        'success': False,
        'error': {
            'code': code,
            'message': message,
        }
    }
    
    if details:
        response_data['error']['details'] = details
        
    if field_errors:
        response_data['error']['field_errors'] = field_errors
    
    return Response(response_data, status=status_code)


def success_response(
    data: Any = None,
    message: Optional[str] = None,
    status_code: int = status.HTTP_200_OK
) -> Response:
    """
    Create standardized success response
    
    Args:
        data: Response data
        message: Optional success message
        status_code: HTTP status code
        
    Returns:
        DRF Response with standardized success format
    """
    response_data = {
        'success': True,
    }
    
    if message:
        response_data['message'] = message
        
    if data is not None:
        response_data['data'] = data
    
    return Response(response_data, status=status_code)


def validation_error_response(
    field_errors: Dict[str, List[str]],
    message: str = 'Validation failed'
) -> Response:
    """
    Create validation error response
    
    Args:
        field_errors: Dictionary mapping field names to error messages
        message: General validation error message
        
    Returns:
        DRF Response with validation error format
    """
    return error_response(
        message=message,
        code=ErrorCode.VALIDATION_ERROR,
        field_errors=field_errors,
        status_code=status.HTTP_400_BAD_REQUEST
    )


def not_found_response(
    resource: str,
    identifier: Any = None
) -> Response:
    """
    Create not found error response
    
    Args:
        resource: Resource type (e.g., 'Payment', 'Invoice')
        identifier: Resource identifier (ID, slug, etc.)
        
    Returns:
        DRF Response with not found error
    """
    message = f"{resource} not found"
    if identifier:
        message += f": {identifier}"
    
    code_map = {
        'Payment': ErrorCode.PAYMENT_NOT_FOUND,
        'Invoice': ErrorCode.INVOICE_NOT_FOUND,
        'Subscription': ErrorCode.SUBSCRIPTION_NOT_FOUND,
    }
    
    return error_response(
        message=message,
        code=code_map.get(resource, ErrorCode.INTERNAL_ERROR),
        status_code=status.HTTP_404_NOT_FOUND
    )


def unauthorized_response(
    message: str = 'Authentication required'
) -> Response:
    """Create unauthorized error response"""
    return error_response(
        message=message,
        code=ErrorCode.UNAUTHORIZED,
        status_code=status.HTTP_401_UNAUTHORIZED
    )


def forbidden_response(
    message: str = 'You do not have permission to perform this action'
) -> Response:
    """Create forbidden error response"""
    return error_response(
        message=message,
        code=ErrorCode.FORBIDDEN,
        status_code=status.HTTP_403_FORBIDDEN
    )
