from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """

    def has_object_permission(self, request, view, obj):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True

        # Write permissions are only allowed to the owner of the object.
        # Assumes the model instance has an `user` attribute.
        if hasattr(obj, "user"):
            return obj.user == request.user
        return False


class IsStaffOrReadOnly(permissions.BasePermission):
    """
    Custom permission to only allow staff to edit it.
    """

    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True
        return request.user and request.user.is_staff


class IsAdminWithSecondFactor(permissions.BasePermission):
    """
    Requires admin status AND at least one configured second factor.
    
    Accepts either:
    - TOTP (MFA/Authenticator app)
    - WebAuthn (Passkey/Security key)
    
    This permission ensures that admin users have a second factor configured
    before they can access sensitive admin endpoints.
    """

    message = "Admin access requires MFA or Passkey to be configured."

    def has_permission(self, request, view):
        user = request.user
        
        # Must be authenticated
        if not user or not user.is_authenticated:
            return False
        
        # Must be admin (staff, superuser, or ADMIN role)
        if not self._is_admin(user):
            self.message = "You do not have admin privileges."
            return False
        
        # Must have at least one second factor configured
        if not self._has_second_factor(user):
            self.message = "Admin access requires MFA or Passkey to be configured."
            return False
        
        return True
    
    def _is_admin(self, user) -> bool:
        """Check if user has admin privileges."""
        if user.is_superuser:
            return True
        if user.is_staff:
            return True
        # Check custom role field if it exists
        if hasattr(user, "role") and user.role in ("ADMIN", "SUPERUSER"):
            return True
        return False
    
    def _has_second_factor(self, user) -> bool:
        """Check if user has at least one second factor configured."""
        try:
            from allauth.mfa.models import Authenticator
            
            # Check for TOTP or WebAuthn authenticators
            return Authenticator.objects.filter(
                user=user,
                type__in=[Authenticator.Type.TOTP, Authenticator.Type.WEBAUTHN]
            ).exists()
        except ImportError:
            # allauth.mfa not installed
            return False
        except Exception:
            # Any other error, fail closed (deny access)
            return False
