"""
Custom decorators for PX Source User access control.

Provides decorators to:
- Restrict views to source users only
- Block source users from admin pages
"""
from functools import wraps
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.contrib import messages
from django.utils.translation import gettext_lazy as _


def source_user_required(view_func):
    """
    Decorator to restrict access to source users only.
    
    Use this on views that should ONLY be accessible to source users.
    Blocks all admin/management/staff pages.
    
    Example:
        @source_user_required
        def source_user_dashboard(request):
            # Only source users can access this
    """
    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        # Check if user has source user profile
        if not hasattr(request.user, 'source_user_profile'):
            raise PermissionDenied(
                _("Access denied. Source user privileges required.")
            )
        
        source_user = request.user.source_user_profile
        
        # Check if source user is active
        if not source_user.is_active:
            # Log out the user
            from django.contrib.auth import logout
            logout(request)
            messages.error(
                request,
                _("Your source user account is inactive. Please contact your administrator.")
            )
            return redirect('accounts:login')
        
        # Store source_user and source in request for easy access
        request.source_user = source_user
        request.source = source_user.source
        
        return view_func(request, *args, **kwargs)
    
    return _wrapped_view


def block_source_user(view_func):
    """
    Decorator to BLOCK source users from accessing admin pages.
    
    Use this on admin/management views that source users should NOT access.
    Allows all other users (PX Admin, Hospital Admin, Department Manager, etc.)
    
    Example:
        @block_source_user
        def source_list(request):
            # Source users CANNOT access this
    """
    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        # Check if user is ONLY a source user (no other admin roles)
        if _is_pure_source_user(request.user):
            messages.error(
                request,
                _("Access denied. Source users cannot access admin pages.")
            )
            return redirect('px_sources:source_user_dashboard')
        
        return view_func(request, *args, **kwargs)
    
    return _wrapped_view


def source_user_or_admin(view_func):
    """
    Decorator that allows both source users AND admins.
    
    Use this on views that should be accessible to:
    - Source users (for their own data)
    - PX Admins, Hospital Admins, Department Managers
    
    Example:
        @source_user_or_admin
        def complaint_detail(request, pk):
            # Both source users and admins can view complaints
    """
    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        # Allow if user has admin roles
        if _has_admin_role(request.user):
            return view_func(request, *args, **kwargs)
        
        # Allow if user is an active source user
        if hasattr(request.user, 'source_user_profile'):
            source_user = request.user.source_user_profile
            if source_user.is_active:
                request.source_user = source_user
                request.source = source_user.source
                return view_func(request, *args, **kwargs)
        
        # Deny access
        raise PermissionDenied(_("Access denied."))
    
    return _wrapped_view


def _is_pure_source_user(user):
    """
    Check if user is ONLY a source user with no admin roles.
    
    Returns True if:
    - User is in 'PX Source User' group
    - User is NOT in any admin groups
    """
    admin_groups = ['PX Admin', 'Hospital Admin', 'Department Manager']
    
    # Check if user has any admin roles
    has_admin_role = user.groups.filter(name__in=admin_groups).exists()
    
    if has_admin_role:
        return False
    
    # Check if user is a source user
    has_source_user_profile = hasattr(user, 'source_user_profile')
    
    if has_source_user_profile:
        source_user = user.source_user_profile
        if source_user.is_active:
            return True
    
    return False


def _has_admin_role(user):
    """
    Check if user has any admin role.
    """
    admin_groups = ['PX Admin', 'Hospital Admin', 'Department Manager']
    return user.groups.filter(name__in=admin_groups).exists()


def px_admin_required(view_func):
    """
    Decorator to restrict access to PX Admins only.
    
    Use this on views that should ONLY be accessible to PX Admins.
    """
    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if not user.is_px_admin():
            messages.error(
                request,
                _("Access denied. PX Admin privileges required.")
            )
            return redirect('dashboard:dashboard')
        
        return view_func(request, *args, **kwargs)
    
    return _wrapped_view
