from functools import wraps
from django.core.exceptions import PermissionDenied
from django.shortcuts import redirect
from django.contrib import messages
from .models import TenantUserRole

# Allowed roles for staff/admin actions
STAFF_ROLES = [
    'admin', 'campaign_manager', 'campaign_staff',
    'system_admin', 'campaign_admin'
]

def get_user_role(user, tenant):
    if user.is_superuser:
        return 'admin'
    role_obj = TenantUserRole.objects.filter(user=user, tenant=tenant).first()
    if role_obj:
        return role_obj.role
    return None

def has_role(user, tenant, roles):
    if user.is_superuser:
        return True
    if not tenant:
        return False
    user_role = get_user_role(user, tenant)
    return user_role in roles

def is_block_walker(user):
    return user.groups.filter(name='Block Walker').exists()

def can_view_voters(user, tenant):
    if user.has_perm("core.view_voter"):
        return True
    if user.is_superuser:
        return True
    # If they can edit, they can view
    if can_edit_voter(user, tenant):
        return True
    # All authenticated users with a tenant role can usually view voters in our app
    # but we should restrict it if they have NO role and NO permission.
    role = get_user_role(user, tenant)
    if role: # Any role (even if not in STAFF_ROLES) allows viewing voters? 
             # Block Walkers don't have a TenantUserRole usually, they have a Group.
        return True
    return False

def can_view_donations(user, tenant):
    if user.has_perm("core.view_donation"):
        return True
    if user.is_superuser:
        return True
    role = get_user_role(user, tenant)
    if role in STAFF_ROLES:
        return True
    return False

def can_edit_voter(user, tenant):
    if user.has_perm("core.change_voter"):
        return True
    if user.is_superuser:
        return True
    role = get_user_role(user, tenant)
    if role in STAFF_ROLES:
        return True
    return False

def can_view_volunteers(user, tenant):
    if user.has_perm("core.view_volunteer"):
        return True
    if user.is_superuser:
        return True
    role = get_user_role(user, tenant)
    if role in STAFF_ROLES:
        return True
    return False

def can_edit_volunteer(user, tenant):
    if user.has_perm("core.change_volunteer"):
        return True
    if user.is_superuser:
        return True
    role = get_user_role(user, tenant)
    if role in STAFF_ROLES:
        return True
    return False

def role_required(roles, permission=None):
    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            from .models import Tenant
            tenant_id = request.session.get('tenant_id')
            if not tenant_id:
                if request.user.is_superuser:
                    return view_func(request, *args, **kwargs)
                messages.warning(request, "Please select a campaign first.")
                return redirect('index')
            
            tenant = Tenant.objects.filter(id=tenant_id).first()
            if not tenant:
                messages.warning(request, "Campaign not found.")
                return redirect('index')

            # Check roles first
            if has_role(request.user, tenant, roles):
                return view_func(request, *args, **kwargs)
            
            # Check for specific permission if provided
            if permission and request.user.has_perm(permission):
                return view_func(request, *args, **kwargs)

            messages.error(request, "You do not have permission to perform this action.")
            return redirect('index')
        return _wrapped_view
    return decorator
