"""
Permission Services - Comprehensive permission checking utilities.

5-Layer Authorization Pipeline:
1. Tenant Isolation — scoped via middleware, always enforced
2. Module Access — does user's tenant have access to this module?
3. Resource/CRUD Permission — role-based + action-based
4. RAIC (Relationship-based) — dynamic per-object permissions
5. Explicit User Override — user-specific allow/deny (deny > allow)

این سرویس سیستم permission یکپارچه پلتفرم را فراهم می‌کند.
"""
import logging
from typing import Optional, List, Dict, Any, Set, TYPE_CHECKING

from django.db.models import Model, QuerySet, Q
from django.core.cache import cache

from .models import (
    Permission, UserRole, Role, FieldPermission,
    UserPermission, ObjectRelation, RAICPolicy,
)

if TYPE_CHECKING:
    from apps.core.auth.models import User

logger = logging.getLogger('apps')


def _safe_delete_pattern(pattern: str):
    """Cache delete_pattern that works with both Redis and LocMemCache."""
    try:
        if hasattr(cache, 'delete_pattern'):
            cache.delete_pattern(pattern)
    except Exception:
        pass


class PermissionService:
    """
    Unified service for checking user permissions.
    
    این سرویس تمام انواع permission check ها رو handle می‌کنه:
    - Permission-based (آیا کاربر permission خاصی داره؟)
    - Role-based (آیا کاربر role خاصی داره؟)
    - Scope-based (آیا permission در scope مشخصی هست؟)
    - Object-based (آیا کاربر به object خاصی دسترسی داره؟)
    - Module-based (آیا کاربر به module خاصی دسترسی داره؟)
    """
    
    CACHE_TTL = 300  # 5 minutes
    
    # ==================== Basic Permission Checks ====================
    
    @staticmethod
    def has_permission(user: 'User', permission_codename: str) -> bool:
        """
        Check if user has a specific permission.
        
        Args:
            user: The user to check
            permission_codename: The permission codename (e.g., 'users.view')
            
        Returns:
            bool: True if user has the permission
        """
        if not user or not user.is_authenticated:
            return False
            
        if user.is_superuser:
            return True
        
        # Check cache first
        cache_key = f"user_perm:{user.id}:{permission_codename}"
        cached = cache.get(cache_key)
        if cached is not None:
            return cached
        
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role').prefetch_related('role__role_permissions__permission')
        
        has_perm = False
        for user_role in user_roles:
            permissions = user_role.role.get_all_permissions()
            if any(p.codename == permission_codename for p in permissions):
                has_perm = True
                break
        
        cache.set(cache_key, has_perm, PermissionService.CACHE_TTL)
        return has_perm
    
    @staticmethod
    def has_any_permission(user: 'User', permission_codenames: List[str]) -> bool:
        """
        Check if user has any of the specified permissions.
        """
        return any(
            PermissionService.has_permission(user, perm) 
            for perm in permission_codenames
        )
    
    @staticmethod
    def has_all_permissions(user: 'User', permission_codenames: List[str]) -> bool:
        """
        Check if user has all of the specified permissions.
        """
        return all(
            PermissionService.has_permission(user, perm) 
            for perm in permission_codenames
        )
    
    # ==================== 5-Layer Pipeline ====================
    
    @staticmethod
    def evaluate_access(
        user: 'User',
        permission_codename: str,
        obj: Optional[Model] = None,
        module: str = '',
        request=None,
    ) -> bool:
        """
        Full 5-layer authorization pipeline.
        
        1. Tenant Isolation — already enforced by middleware
        2. Module Access — check if user's tenant has module enabled
        3. Resource/CRUD Permission — role-based check
        4. RAIC — relationship-based check on specific object
        5. Explicit User Override — user-specific allow/deny
        
        Returns True if access is granted, False otherwise.
        """
        if not user or not user.is_authenticated:
            return False
        
        # SuperAdmin bypass everything
        if user.is_superuser:
            return True
        
        # Layer 2: Module Access
        if module:
            if not PermissionService.has_module_access(user, module):
                PermissionService._log_access_denied(
                    user, permission_codename, module=module, request=request
                )
                return False
        elif '.' in permission_codename:
            # Extract module from permission codename (e.g., 'pm.task.create' → 'pm')
            mod = permission_codename.split('.')[0]
            if not PermissionService.has_module_access(user, mod):
                PermissionService._log_access_denied(
                    user, permission_codename, module=mod, request=request
                )
                return False
        
        # Layer 5: Explicit User Override (checked first — deny > allow)
        override = PermissionService._check_user_override(user, permission_codename)
        if override is not None:
            if not override:
                PermissionService._log_access_denied(
                    user, permission_codename, module=module, request=request
                )
            return override
        
        # Layer 3: Resource/CRUD Permission (role-based)
        has_role_perm = PermissionService.has_permission(user, permission_codename)
        
        # Layer 4: RAIC (relationship-based) — only applies to object-level checks
        if obj is not None:
            has_raic = PermissionService._check_raic(user, permission_codename, obj)
            # RAIC can grant access even if role doesn't have it, 
            # but only within the same module scope
            if has_raic:
                return True
        
        if not has_role_perm:
            PermissionService._log_access_denied(
                user, permission_codename, module=module, request=request
            )
        
        return has_role_perm
    
    @staticmethod
    def _check_user_override(
        user: 'User',
        permission_codename: str,
    ) -> Optional[bool]:
        """
        Check explicit user permission overrides.
        
        Returns:
            True if explicitly allowed
            False if explicitly denied
            None if no override exists
        
        Rule: Explicit Deny > Explicit Allow
        """
        cache_key = f"user_override:{user.id}:{permission_codename}"
        cached = cache.get(cache_key)
        if cached is not None:
            return cached if cached != '__none__' else None
        
        overrides = UserPermission.objects.filter(
            user=user,
            permission__codename=permission_codename,
        ).select_related('permission')
        
        result = None
        for override in overrides:
            if not override.is_active():
                continue
            if not override.allow:
                # Explicit deny always wins
                result = False
                break
            result = True
        
        cache.set(cache_key, result if result is not None else '__none__', PermissionService.CACHE_TTL)
        return result
    
    @staticmethod
    def _check_raic(
        user: 'User',
        permission_codename: str,
        obj: Model,
    ) -> bool:
        """
        Check RAIC (Relationship-based) permission on a specific object.
        
        Steps:
        1. Get user's relations to the object
        2. Look up RAIC policies for those relations + permission
        3. If any active policy matches, return True
        """
        object_type = f"{obj._meta.app_label}.{obj._meta.model_name}"
        object_id = str(obj.pk) if obj.pk else ''
        
        # Cache key for user's relations to this object
        cache_key = f"raic:{user.id}:{object_type}:{object_id}:{permission_codename}"
        cached = cache.get(cache_key)
        if cached is not None:
            return cached
        
        # Get user's relations to this object
        relations = ObjectRelation.objects.filter(
            user=user,
            object_type=object_type,
            object_id=object_id,
        ).values_list('relation_type', flat=True)
        
        if not relations:
            cache.set(cache_key, False, PermissionService.CACHE_TTL)
            return False
        
        # Check RAIC policies
        has_access = RAICPolicy.objects.filter(
            object_type=object_type,
            relation_type__in=list(relations),
            permission__codename=permission_codename,
            is_active=True,
        ).exists()
        
        cache.set(cache_key, has_access, PermissionService.CACHE_TTL)
        return has_access
    
    @staticmethod
    def _log_access_denied(user, permission, module='', request=None):
        """Log access denied event asynchronously."""
        try:
            from apps.services.audit_log.tasks import log_access_denied_async
            ip_address = None
            user_agent = ''
            tenant_schema = ''
            if request:
                x_forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
                ip_address = x_forwarded.split(',')[0].strip() if x_forwarded else request.META.get('REMOTE_ADDR')
                user_agent = request.META.get('HTTP_USER_AGENT', '')[:500]
                tenant_obj = getattr(request, 'tenant', None)
                if tenant_obj:
                    tenant_schema = getattr(tenant_obj, 'schema_name', '')
            
            log_access_denied_async.delay(
                user_id=user.id if user else None,
                permission=permission,
                module=module,
                ip_address=ip_address,
                user_agent=user_agent,
                tenant_schema=tenant_schema,
            )
        except Exception as e:
            logger.warning(f"Failed to log access denied: {e}")
    
    # ==================== RAIC Management ====================
    
    @staticmethod
    def register_relation(
        user: 'User',
        object_type: str,
        object_id: str,
        relation_type: str,
        module: str = '',
        metadata: dict | None = None,
    ) -> ObjectRelation:
        """Register a user's relationship to an object."""
        relation, _ = ObjectRelation.objects.get_or_create(
            user=user,
            object_type=object_type,
            object_id=str(object_id),
            relation_type=relation_type,
            defaults={
                'module': module,
                'metadata': metadata or {},
            }
        )
        # Invalidate RAIC cache for this user+object
        _safe_delete_pattern(f"raic:{user.id}:{object_type}:{object_id}:*")
        return relation
    
    @staticmethod
    def remove_relation(
        user: 'User',
        object_type: str,
        object_id: str,
        relation_type: str,
    ) -> bool:
        """Remove a user's relationship to an object."""
        deleted, _ = ObjectRelation.objects.filter(
            user=user,
            object_type=object_type,
            object_id=str(object_id),
            relation_type=relation_type,
        ).delete()
        if deleted:
            _safe_delete_pattern(f"raic:{user.id}:{object_type}:{object_id}:*")
        return deleted > 0
    
    @staticmethod
    def get_object_relations(
        object_type: str,
        object_id: str,
    ) -> List[ObjectRelation]:
        """Get all relations for an object."""
        return list(ObjectRelation.objects.filter(
            object_type=object_type,
            object_id=str(object_id),
        ).select_related('user'))
    
    @staticmethod
    def get_user_relations(
        user: 'User',
        module: str = '',
    ) -> List[ObjectRelation]:
        """Get all relations for a user, optionally filtered by module."""
        qs = ObjectRelation.objects.filter(user=user)
        if module:
            qs = qs.filter(module=module)
        return list(qs)

    # ==================== Role-based Checks ====================
    
    @staticmethod
    def has_role(user: 'User', role_codename: str) -> bool:
        """
        Check if user has a specific role.
        """
        if not user or not user.is_authenticated:
            return False
            
        return UserRole.objects.filter(
            user=user,
            role__slug=role_codename
        ).exists()
    
    @staticmethod
    def has_any_role(user: 'User', role_codenames: List[str]) -> bool:
        """
        Check if user has any of the specified roles.
        """
        if not user or not user.is_authenticated:
            return False
            
        return UserRole.objects.filter(
            user=user,
            role__slug__in=role_codenames
        ).exists()
    
    @staticmethod
    def get_user_roles(user: 'User') -> List[Role]:
        """
        Get all roles assigned to a user.
        """
        if not user or not user.is_authenticated:
            return []
            
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role')
        
        return [ur.role for ur in user_roles]
    
    # ==================== Organization Unit Scoped Checks ====================
    
    @staticmethod
    def has_permission_in_org_unit(
        user: 'User', 
        permission_codename: str, 
        org_unit_id: int
    ) -> bool:
        """
        Check if user has permission in a specific organizational unit.
        
        این متد چک می‌کنه که آیا کاربر permission مشخصی رو در یک واحد سازمانی داره یا نه.
        همچنین سلسله مراتب رو در نظر می‌گیره (مثلا اگر در parent داشته باشه، در child هم داره).
        """
        if not user or not user.is_authenticated:
            return False
            
        if user.is_superuser:
            return True
        
        from apps.core.organization.models import OrganizationalUnit
        
        # Get user's roles with their org unit scopes
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role', 'organizational_unit').prefetch_related('role__role_permissions__permission')
        
        # Get the target org unit and its ancestor path
        try:
            target_org_unit = OrganizationalUnit.objects.get(id=org_unit_id)
        except OrganizationalUnit.DoesNotExist:
            return False
        
        # Collect all ancestor IDs
        ancestor_ids = set()
        if target_org_unit.path:
            ancestor_ids = set(target_org_unit.path.split('/'))
        ancestor_ids.add(str(org_unit_id))
        
        for user_role in user_roles:
            # Check if role has the permission
            if not any(p.codename == permission_codename for p in user_role.role.get_all_permissions()):
                continue
            
            # Global role (no organizational_unit restriction)
            if user_role.organizational_unit is None:
                return True
            
            # Check if user's role organizational_unit covers the target
            if str(user_role.organizational_unit_id) in ancestor_ids:
                return True
        
        return False
    
    @staticmethod
    def get_user_org_units(user: 'User') -> List[int]:
        """
        Get all organizational unit IDs the user has access to.
        """
        if not user or not user.is_authenticated:
            return []
        
        from apps.core.organization.models import UserOrganizationalUnit
        
        # Direct assignments
        direct_units = UserOrganizationalUnit.objects.filter(
            user=user
        ).values_list('organizational_unit_id', flat=True)
        
        # From roles
        role_units = UserRole.objects.filter(
            user=user,
            organizational_unit__isnull=False
        ).values_list('organizational_unit_id', flat=True)
        
        return list(set(direct_units) | set(role_units))
    
    @staticmethod
    def get_accessible_org_units_for_permission(
        user: 'User', 
        permission_codename: str
    ) -> List[int]:
        """
        Get all org unit IDs where user has the specified permission.
        Returns empty list if user has global permission (no org restrictions).
        """
        if not user or not user.is_authenticated:
            return []
            
        if user.is_superuser:
            return []  # Empty means global access
        
        from apps.core.organization.models import OrganizationalUnit
        
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role', 'organizational_unit').prefetch_related('role__role_permissions__permission')
        
        org_unit_ids = set()
        has_global = False
        
        for user_role in user_roles:
            if not any(p.codename == permission_codename for p in user_role.role.get_all_permissions()):
                continue
            
            if user_role.organizational_unit is None:
                has_global = True
                break
            
            # Add this org unit and all descendants
            org_unit_ids.add(user_role.organizational_unit_id)
            descendants = OrganizationalUnit.objects.filter(
                path__startswith=user_role.organizational_unit.get_full_path()
            ).values_list('id', flat=True)
            org_unit_ids.update(descendants)
        
        if has_global:
            return []
            
        return list(org_unit_ids)
    
    # ==================== Module-based Access Control ====================
    
    @staticmethod
    def has_module_access(user: 'User', module_name: str) -> bool:
        """
        Check if user's tenant has access to a specific module.
        """
        if not user or not user.is_authenticated:
            return False
        
        from apps.core.module_registry.services import ModuleRegistryService
        
        return ModuleRegistryService.is_module_enabled_for_user(user, module_name)
    
    @staticmethod
    def has_module_feature(user: 'User', module_name: str, feature_name: str) -> bool:
        """
        Check if user has access to a specific module feature.
        """
        if not user or not user.is_authenticated:
            return False
        
        from apps.core.module_registry.services import ModuleRegistryService
        
        return ModuleRegistryService.is_feature_enabled_for_user(user, module_name, feature_name)
    
    # ==================== Object-level Permission Checks ====================
    
    @staticmethod
    def has_object_permission(
        user: 'User', 
        permission_codename: str, 
        obj: Model
    ) -> bool:
        """
        Check if user has permission on a specific object.
        
        این متد ترتیبی چک می‌کنه:
        1. django-guardian object-level permissions
        2. Data policy rules
        3. Organization unit scope
        4. Role-based permissions
        """
        if not user or not user.is_authenticated:
            return False
            
        if user.is_superuser:
            return True
        
        # 1. Check django-guardian object-level permission
        try:
            from guardian.shortcuts import get_perms
            obj_perms = get_perms(user, obj)
            if permission_codename in obj_perms:
                return True
        except ImportError:
            pass
        
        # 2. Check data policies
        if PermissionService._check_data_policy_access(user, obj):
            # Continue to other checks
            pass
        else:
            return False
        
        # 3. Check org unit scope if object has organizational_unit field
        ou_id = getattr(obj, 'organizational_unit_id', None) or getattr(obj, 'org_unit_id', None)
        if ou_id:
            if not PermissionService.has_permission_in_org_unit(
                user, permission_codename, ou_id
            ):
                return False
        
        # 4. Fallback to role-based permission
        return PermissionService.has_permission(user, permission_codename)
    
    @staticmethod
    def _check_data_policy_access(user: 'User', obj: Model) -> bool:
        """
        Check if data policies allow access to this object.
        """
        from apps.core.data_policy.services import DataPolicyService
        
        # Get model name
        model_name = f"{obj._meta.app_label}.{obj._meta.model_name}"
        
        # Apply policies as filter and check if object is in result
        try:
            queryset = type(obj).objects.filter(pk=obj.pk)
            filtered = DataPolicyService.apply_policies(queryset, user, model_name)
            return filtered.exists()
        except Exception:
            # If no policies defined, allow access
            return True
    
    # ==================== Field-level Permission Checks ====================
    
    @staticmethod
    def get_allowed_fields(
        user: 'User', 
        model_name: str, 
        action: str = 'view'
    ) -> Set[str]:
        """
        Get list of fields user can access for a model.
        
        Args:
            user: The user to check
            model_name: Full model name (e.g., 'auth.user')
            action: 'view' or 'edit'
            
        Returns:
            Set of field names user can access
        """
        if not user or not user.is_authenticated:
            return set()
            
        if user.is_superuser:
            # Return all fields
            return {'*'}  # Special marker for all fields
        
        # Get user's roles
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role')
        role_ids = [ur.role_id for ur in user_roles]
        
        # Parse model_name into module and resource
        parts = model_name.split('.')
        if len(parts) >= 2:
            module_name, resource_name = parts[0], parts[1]
        else:
            module_name, resource_name = model_name, ''
        
        # Get field permissions for these roles
        field_perms = FieldPermission.objects.filter(
            role_id__in=role_ids,
            module=module_name,
            resource=resource_name,
        )
        
        if action == 'view':
            return set(
                fp.field_name for fp in field_perms 
                if fp.access_level in ('readonly', 'editable', 'masked')
            )
        else:  # edit
            return set(
                fp.field_name for fp in field_perms 
                if fp.access_level == 'editable'
            )
    
    @staticmethod
    def can_access_field(
        user: 'User', 
        model_name: str, 
        field_name: str,
        action: str = 'view'
    ) -> bool:
        """
        Check if user can access a specific field.
        """
        if not user or not user.is_authenticated:
            return False
            
        if user.is_superuser:
            return True
        
        allowed_fields = PermissionService.get_allowed_fields(user, model_name, action)
        
        # '*' means all fields allowed
        if '*' in allowed_fields:
            return True
            
        return field_name in allowed_fields
    
    @staticmethod
    def filter_fields(
        user: 'User',
        model_name: str,
        data: Dict[str, Any],
        action: str = 'view'
    ) -> Dict[str, Any]:
        """
        Filter a dictionary to only include fields user can access.
        
        Useful for filtering serializer output.
        """
        if user.is_superuser:
            return data
            
        allowed = PermissionService.get_allowed_fields(user, model_name, action)
        
        if '*' in allowed:
            return data
            
        return {k: v for k, v in data.items() if k in allowed}
    
    # ==================== Data Scope Functions ====================
    
    @staticmethod
    def get_user_data_scopes(user: 'User') -> list:
        """
        Get the effective data scopes for a user via data_policy module.
        """
        if not user or not user.is_authenticated:
            return []
        
        try:
            from apps.core.data_policy.models import UserDataScope
            return list(
                UserDataScope.objects.filter(user=user)
                .select_related('scope')
                .values_list('scope', flat=True)
            )
        except Exception:
            return []
    
    @staticmethod
    def apply_data_scope_to_queryset(
        queryset: QuerySet, 
        user: 'User'
    ) -> QuerySet:
        """
        Apply user's data scope to filter a queryset.
        
        This combines:
        - Organization unit filtering
        - Data policy rules
        - Module access restrictions
        """
        if not user or not user.is_authenticated:
            return queryset.none()
            
        if user.is_superuser:
            return queryset
        
        model = queryset.model
        model_name = f"{model._meta.app_label}.{model._meta.model_name}"
        
        # Apply data policies
        from apps.core.data_policy.services import DataPolicyService
        queryset = DataPolicyService.apply_policies(queryset, user, model_name)
        
        # Apply org unit filter if model has organizational_unit field
        ou_field = None
        if hasattr(model, 'organizational_unit_id'):
            ou_field = 'organizational_unit_id'
        elif hasattr(model, 'org_unit_id'):
            ou_field = 'org_unit_id'
        
        if ou_field:
            accessible_units = PermissionService.get_user_org_units(user)
            if accessible_units:
                queryset = queryset.filter(**{f'{ou_field}__in': accessible_units})
        
        return queryset
    
    # ==================== Permission Assignment ====================
    
    @staticmethod
    def assign_role(
        user: 'User', 
        role: Role, 
        organizational_unit=None,
    ) -> UserRole:
        """
        Assign a role to a user.
        
        Args:
            user: User to assign role to
            role: Role to assign
            organizational_unit: Optional organizational unit to scope the role
        """
        user_role, created = UserRole.objects.update_or_create(
            user=user,
            role=role,
            defaults={
                'organizational_unit': organizational_unit,
            }
        )
        
        # Invalidate cache
        PermissionService._invalidate_user_cache(user)
        
        return user_role
    
    @staticmethod
    def revoke_role(user: 'User', role: Role) -> bool:
        """
        Revoke a role from a user.
        """
        deleted, _ = UserRole.objects.filter(user=user, role=role).delete()
        
        if deleted:
            PermissionService._invalidate_user_cache(user)
            
        return deleted > 0
    
    # ==================== Permission Queries ====================
    
    @staticmethod
    def get_user_permissions(user: 'User') -> list[str]:
        """
        Get all permission codenames for a user.
        
        Includes:
        - Role-based permissions (with inheritance)
        - Explicit UserPermission allows
        Excludes:
        - Explicit UserPermission denies
        """
        if not user or not user.is_authenticated:
            return []
            
        if user.is_superuser:
            return list(Permission.objects.values_list('codename', flat=True))
        
        cache_key = f"user_all_perms:{user.id}"
        cached = cache.get(cache_key)
        if cached is not None:
            return cached
        
        permissions = set()
        
        # 1. Role-based permissions
        user_roles = UserRole.objects.filter(
            user=user
        ).select_related('role').prefetch_related('role__role_permissions__permission')
        
        for user_role in user_roles:
            if user_role.is_active():
                for perm in user_role.role.get_all_permissions():
                    permissions.add(perm.codename)
        
        # 2. Explicit UserPermission overrides
        overrides = UserPermission.objects.filter(
            user=user,
        ).select_related('permission')
        
        for override in overrides:
            if override.is_active():
                if override.allow:
                    permissions.add(override.permission.codename)
                else:
                    # Explicit deny — remove from set
                    permissions.discard(override.permission.codename)
        
        result = sorted(permissions)
        cache.set(cache_key, result, PermissionService.CACHE_TTL)
        return result
    
    @staticmethod
    def get_permissions_by_module(user: 'User') -> Dict[str, List[str]]:
        """
        Get user's permissions grouped by module.
        """
        permissions = PermissionService.get_user_permissions(user)
        
        by_module = {}
        for perm in permissions:
            parts = perm.split('.')
            if len(parts) >= 2:
                module = parts[0]
                if module not in by_module:
                    by_module[module] = []
                by_module[module].append(perm)
        
        return by_module
    
    # ==================== Cache Management ====================
    
    @staticmethod
    def _invalidate_user_cache(user: 'User'):
        """
        Invalidate all permission caches for a user.
        """
        # This is a simplified version - in production you might want
        # to use cache tags or a more sophisticated invalidation strategy
        _safe_delete_pattern(f"user_perm:{user.id}:*")
        cache.delete(f"user_all_perms:{user.id}")
    
    @staticmethod
    def clear_all_caches():
        """
        Clear all permission caches.
        """
        _safe_delete_pattern("user_perm:*")
        _safe_delete_pattern("user_all_perms:*")


class PermissionChecker:
    """
    Context manager for checking multiple permissions efficiently.
    
    Usage:
        with PermissionChecker(user) as checker:
            if checker.has('users.view'):
                # do something
            if checker.has('users.edit'):
                # do something else
    """
    
    def __init__(self, user: 'User'):
        self.user = user
        self._permissions: Set[str] = set()
        self._loaded = False
    
    def __enter__(self):
        self._permissions = set(PermissionService.get_user_permissions(self.user))
        self._loaded = True
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self._permissions = set()
        self._loaded = False
    
    def has(self, permission_codename: str) -> bool:
        """Check if user has permission."""
        if self.user.is_superuser:
            return True
        return permission_codename in self._permissions
    
    def has_any(self, codenames: List[str]) -> bool:
        """Check if user has any of the permissions."""
        if self.user.is_superuser:
            return True
        return bool(self._permissions & set(codenames))
    
    def has_all(self, codenames: List[str]) -> bool:
        """Check if user has all permissions."""
        if self.user.is_superuser:
            return True
        return set(codenames).issubset(self._permissions)
