"""
Transaction management utilities.
Provides decorators and context managers for database transactions.
"""

from functools import wraps
from typing import Any, Callable

from flask import current_app

from app import db


def transactional(func: Callable) -> Callable:
    """
    Decorator to wrap a function in a database transaction.

    Automatically commits on success, rolls back on exception.

    Usage:
        @transactional
        def create_something():
            # Database operations
            return result
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            result = func(*args, **kwargs)
            db.session.commit()
            return result
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Transaction failed in {func.__name__}: {e}")
            raise

    return wrapper


class Transaction:
    """
    Context manager for database transactions.

    Usage:
        with Transaction():
            # Database operations
            # Auto-commits on success, rolls back on exception
    """

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            # No exception - commit
            try:
                db.session.commit()
            except Exception as e:
                db.session.rollback()
                current_app.logger.error(f"Transaction commit failed: {e}")
                raise
        else:
            # Exception occurred - rollback
            db.session.rollback()
            current_app.logger.error(f"Transaction rolled back due to: {exc_val}")
        return False  # Don't suppress exceptions


def safe_transaction(func: Callable) -> Callable:
    """
    Decorator for safe transactions that don't raise exceptions.

    Returns a tuple of (success: bool, result: Any, error: str)

    Usage:
        @safe_transaction
        def create_something():
            # Database operations
            return result

        success, result, error = create_something()
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            result = func(*args, **kwargs)
            db.session.commit()
            return True, result, None
        except Exception as e:
            db.session.rollback()
            error_msg = str(e)
            current_app.logger.error(f"Safe transaction failed in {func.__name__}: {error_msg}")
            return False, None, error_msg

    return wrapper
