"""
Decorator for automatic audit logging of financial operations.
"""
from functools import wraps
from typing import Callable, Any
from fastapi import Request
from sqlalchemy.orm import Session
from ...analytics.services.audit_service import audit_service
from ...shared.config.logging_config import get_logger

logger = get_logger(__name__)

def audit_financial_operation(action: str, resource_type: str):
    """
    Decorator to automatically log financial operations to audit trail.
    
    Usage:
        @audit_financial_operation('payment_refunded', 'payment')
        async def refund_payment(...):
            ...
    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        async def wrapper(*args, **kwargs):
            # Extract request and db from function arguments
            request: Request = None
            db: Session = None
            current_user = None
            
            # Find request and db in kwargs or args
            for arg in list(args) + list(kwargs.values()):
                if isinstance(arg, Request):
                    request = arg
                elif isinstance(arg, Session):
                    db = arg
                elif hasattr(arg, 'id') and hasattr(arg, 'email'):  # Likely a User object
                    current_user = arg
            
            # Get request from kwargs if not found
            if not request and 'request' in kwargs:
                request = kwargs['request']
            if not db and 'db' in kwargs:
                db = kwargs['db']
            if not current_user and 'current_user' in kwargs:
                current_user = kwargs['current_user']
            
            # Extract resource_id from function arguments if available
            resource_id = None
            if 'id' in kwargs:
                resource_id = kwargs['id']
            elif len(args) > 0 and isinstance(args[0], int):
                resource_id = args[0]
            
            # Get client info
            client_ip = None
            user_agent = None
            request_id = None
            if request:
                client_ip = request.client.host if request.client else None
                user_agent = request.headers.get('User-Agent')
                request_id = getattr(request.state, 'request_id', None)
            
            try:
                # Execute the function
                result = await func(*args, **kwargs)
                
                # Log successful operation
                if db and current_user:
                    await audit_service.log_action(
                        db=db,
                        action=action,
                        resource_type=resource_type,
                        user_id=current_user.id if current_user else None,
                        resource_id=resource_id,
                        ip_address=client_ip,
                        user_agent=user_agent,
                        request_id=request_id,
                        details={
                            'function': func.__name__,
                            'result': 'success'
                        },
                        status='success'
                    )
                
                return result
            except Exception as e:
                # Log failed operation
                if db and current_user:
                    await audit_service.log_action(
                        db=db,
                        action=action,
                        resource_type=resource_type,
                        user_id=current_user.id if current_user else None,
                        resource_id=resource_id,
                        ip_address=client_ip,
                        user_agent=user_agent,
                        request_id=request_id,
                        details={
                            'function': func.__name__,
                            'result': 'failed',
                            'error': str(e)
                        },
                        status='failed',
                        error_message=str(e)
                    )
                
                raise
        
        return wrapper
    return decorator

