"""
Standardized Permission Classes
Provides consistent permission checking across all endpoints
"""
from rest_framework import permissions
from rest_framework.exceptions import PermissionDenied


class IsAuthenticatedAndActive(permissions.BasePermission):
    """
    Permission class that requires user to be authenticated and active
    Base permission for most endpoints
    """
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # Check if user is active
        if hasattr(request.user, 'is_active'):
            return request.user.is_active
        
        return True


class HasTenantAccess(permissions.BasePermission):
    """
    Permission class that requires user to belong to the tenant/account
    Ensures tenant isolation
    """
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # Get account from request (set by middleware)
        account = getattr(request, 'account', None)
        
        # If no account in request, try to get from user
        if not account and hasattr(request.user, 'account'):
            try:
                account = request.user.account
            except (AttributeError, Exception):
                pass
        
        # Admin/Developer/System account users bypass tenant check
        if request.user and hasattr(request.user, 'is_authenticated') and request.user.is_authenticated:
            try:
                is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and 
                                 request.user.is_admin_or_developer()) if request.user else False
                is_system_user = (hasattr(request.user, 'is_system_account_user') and 
                                request.user.is_system_account_user()) if request.user else False
                
                if is_admin_or_dev or is_system_user:
                    return True
            except (AttributeError, TypeError):
                pass
        
        # Regular users must have account access
        if account:
            # Check if user belongs to this account
            if hasattr(request.user, 'account'):
                try:
                    user_account = request.user.account
                    return user_account == account or user_account.id == account.id
                except (AttributeError, Exception):
                    pass
        
        return False


class IsViewerOrAbove(permissions.BasePermission):
    """
    Permission class that requires viewer, editor, admin, or owner role
    For read-only operations
    """
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # Admin/Developer/System account users always have access
        try:
            is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and 
                             request.user.is_admin_or_developer()) if request.user else False
            is_system_user = (hasattr(request.user, 'is_system_account_user') and 
                            request.user.is_system_account_user()) if request.user else False
            
            if is_admin_or_dev or is_system_user:
                return True
        except (AttributeError, TypeError):
            pass
        
        # Check user role
        if hasattr(request.user, 'role'):
            role = request.user.role
            # viewer, editor, admin, owner all have access
            return role in ['viewer', 'editor', 'admin', 'owner']
        
        # If no role system, allow authenticated users
        return True


class IsEditorOrAbove(permissions.BasePermission):
    """
    Permission class that requires editor, admin, or owner role
    For content operations
    """
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # Admin/Developer/System account users always have access
        try:
            is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and 
                             request.user.is_admin_or_developer()) if request.user else False
            is_system_user = (hasattr(request.user, 'is_system_account_user') and 
                            request.user.is_system_account_user()) if request.user else False
            
            if is_admin_or_dev or is_system_user:
                return True
        except (AttributeError, TypeError):
            pass
        
        # Check user role
        if hasattr(request.user, 'role'):
            role = request.user.role
            # editor, admin, owner have access
            return role in ['editor', 'admin', 'owner']
        
        # If no role system, allow authenticated users
        return True


class IsAdminOrOwner(permissions.BasePermission):
    """
    Permission class that requires admin or owner role only
    For settings, keys, billing operations
    """
    def has_permission(self, request, view):
        if not request.user or not request.user.is_authenticated:
            return False
        
        # Admin/Developer/System account users always have access
        try:
            is_admin_or_dev = (hasattr(request.user, 'is_admin_or_developer') and 
                             request.user.is_admin_or_developer()) if request.user else False
            is_system_user = (hasattr(request.user, 'is_system_account_user') and 
                            request.user.is_system_account_user()) if request.user else False
            
            if is_admin_or_dev or is_system_user:
                return True
        except (AttributeError, TypeError):
            pass
        
        # Check user role
        if hasattr(request.user, 'role'):
            role = request.user.role
            # admin, owner have access
            return role in ['admin', 'owner']
        
        # If no role system, deny by default for security
        return False


