from functools import wraps
from django.shortcuts import redirect
from django.contrib import messages
from django.http import JsonResponse
from django.core.exceptions import PermissionDenied


def require_permission(module, action):
    """
    Decorator to check if user has permission for a specific module and action
    """
    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            if not request.user.is_authenticated:
                return redirect('users:login')
            
            if not request.user.has_permission(module, action):
                # Log the access attempt
                request.user.log_access(
                    action='access_denied',
                    module=module,
                    description=f'Access denied to {module}.{action}',
                    request=request
                )
                
                # Return appropriate response based on request type
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'status': 'error',
                        'message': 'You do not have permission to perform this action.'
                    }, status=403)
                else:
                    messages.error(request, 'You do not have permission to access this page.')
                    return redirect('main_dashboard')
            
            # Log successful access
            request.user.log_access(
                action=action,
                module=module,
                description=f'Accessed {module}.{action}',
                request=request
            )
            
            return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator


def require_role(*roles):
    """
    Decorator to check if user has one of the specified roles
    """
    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            if not request.user.is_authenticated:
                return redirect('users:login')
            
            if request.user.role not in roles:
                # Log the access attempt
                request.user.log_access(
                    action='access_denied',
                    module='role_check',
                    description=f'Access denied - required roles: {roles}, user role: {request.user.role}',
                    request=request
                )
                
                # Return appropriate response based on request type
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'status': 'error',
                        'message': 'You do not have the required role to perform this action.'
                    }, status=403)
                else:
                    messages.error(request, 'You do not have the required role to access this page.')
                    return redirect('main_dashboard')
            
            # Log successful access
            request.user.log_access(
                action='role_access',
                module='role_check',
                description=f'Accessed with role: {request.user.role}',
                request=request
            )
            
            return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator


def admin_required(view_func):
    """
    Decorator to ensure only admins can access a view
    """
    @wraps(view_func)
    def _wrapped_view(request, *args, **kwargs):
        if not request.user.is_authenticated:
            return redirect('users:login')
        
        if not request.user.is_admin():
            # Log the access attempt
            request.user.log_access(
                action='access_denied',
                module='admin_check',
                description='Access denied - admin required',
                request=request
            )
            
            # Return appropriate response based on request type
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'status': 'error',
                    'message': 'Admin access required.'
                }, status=403)
            else:
                messages.error(request, 'Admin access required.')
                return redirect('main_dashboard')
        
        # Log successful access
        request.user.log_access(
            action='admin_access',
            module='admin_check',
            description='Admin access granted',
            request=request
        )
        
        return view_func(request, *args, **kwargs)
    return _wrapped_view


def staff_required(view_func):
    """
    Decorator to ensure only staff members can access a view
    """
    @wraps(view_func)
    def _wrapped_view(request, *args, **kwargs):
        if not request.user.is_authenticated:
            return redirect('users:login')
        
        if request.user.role not in ['admin', 'team_leader', 'loan_officer', 'secretary']:
            # Log the access attempt
            request.user.log_access(
                action='access_denied',
                module='staff_check',
                description='Access denied - staff required',
                request=request
            )
            
            # Return appropriate response based on request type
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'status': 'error',
                    'message': 'Staff access required.'
                }, status=403)
            else:
                messages.error(request, 'Staff access required.')
                return redirect('main_dashboard')
        
        # Log successful access
        request.user.log_access(
            action='staff_access',
            module='staff_check',
            description='Staff access granted',
            request=request
        )
        
        return view_func(request, *args, **kwargs)
    return _wrapped_view 