"""
Error handling utilities
"""
from typing import Optional, Dict, Any
import traceback
from utils.logger import logger


class ProcessingError(Exception):
    """Base exception for processing errors"""
    pass


class DataValidationError(ProcessingError):
    """Raised when data validation fails"""
    pass


class DatabaseError(ProcessingError):
    """Raised when database operations fail"""
    pass


def handle_processing_error(
    error: Exception,
    context: Optional[Dict[str, Any]] = None,
    raise_error: bool = True
) -> Optional[Dict[str, Any]]:
    """
    Handle processing errors with logging and optional error response
    
    Args:
        error: The exception that occurred
        context: Additional context about where the error occurred
        raise_error: Whether to re-raise the error
    
    Returns:
        Error response dict if not raising, None otherwise
    """
    error_info = {
        'error_type': type(error).__name__,
        'error_message': str(error),
        'context': context or {}
    }
    
    # Log the error
    logger.error(
        f"Processing error: {error_info['error_type']} - {error_info['error_message']}",
        extra={'context': context, 'traceback': traceback.format_exc()}
    )
    
    if raise_error:
        raise error
    
    return error_info


def validate_dataframe(df, required_columns: list, operation: str = "operation"):
    """Validate DataFrame has required columns"""
    if df is None or df.empty:
        raise DataValidationError(f"DataFrame is empty for {operation}")
    
    missing_columns = [col for col in required_columns if col not in df.columns]
    if missing_columns:
        raise DataValidationError(
            f"Missing required columns for {operation}: {missing_columns}"
        )


def safe_divide(numerator, denominator, default=0.0):
    """Safely divide two numbers, returning default if denominator is zero or None"""
    if denominator is None or denominator == 0:
        return default
    try:
        return numerator / denominator
    except (TypeError, ZeroDivisionError):
        return default

