"""
Standardized error handling utilities for route handlers.

This module provides decorators and helpers for consistent error handling
across all route handlers.
"""
from functools import wraps
from fastapi import HTTPException
from sqlalchemy.orm import Session
from typing import Callable, Any
from ...shared.config.logging_config import get_logger

logger = get_logger(__name__)


def handle_db_errors(func: Callable) -> Callable:
    """
    Decorator to handle database errors consistently.
    Automatically rolls back transactions on errors.
    
    Usage:
        @router.post('/')
        @handle_db_errors
        async def create_item(..., db: Session = Depends(get_db)):
            db.add(item)
            db.commit()
            return item
    
    Note: This decorator expects 'db' to be in kwargs or as a positional argument.
    """
    @wraps(func)
    async def wrapper(*args, **kwargs):
        # Find db session in kwargs or args
        db = kwargs.get('db')
        if not db:
            # Try to find in args (if db is positional)
            for arg in args:
                if isinstance(arg, Session):
                    db = arg
                    break
        
        try:
            return await func(*args, **kwargs)
        except HTTPException:
            # Re-raise HTTPExceptions as-is (they're intentional)
            raise
        except ValueError as e:
            # ValueErrors are usually validation errors
            if db:
                db.rollback()
            logger.warning(f'ValueError in {func.__name__}: {str(e)}')
            raise HTTPException(status_code=400, detail=str(e))
        except Exception as e:
            # All other exceptions are server errors
            if db:
                db.rollback()
            logger.error(f'Error in {func.__name__}: {type(e).__name__}: {str(e)}', exc_info=True)
            raise HTTPException(status_code=500, detail="Internal server error")
    
    return wrapper


def safe_db_operation(operation: Callable, db: Session, error_message: str = "Database operation failed") -> Any:
    """
    Safely execute a database operation with automatic rollback on error.
    
    Usage:
        result = safe_db_operation(
            lambda: db.add(item) or db.commit(),
            db,
            "Failed to create item"
        )
    
    Args:
        operation: Callable that performs the database operation
        db: Database session
        error_message: Custom error message to use on failure
        
    Returns:
        Result of the operation
        
    Raises:
        HTTPException: If the operation fails
    """
    try:
        return operation()
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f'{error_message}: {type(e).__name__}: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=error_message)

