from rest_framework.permissions import BasePermission, SAFE_METHODS


def is_admin_user(user):
    return bool(
        user
        and user.is_authenticated
        and (user.is_superuser or getattr(user, "role", None) == "admin")
    )


class IsAdminUserRole(BasePermission):
    """
    Allows access only to users with the 'admin' role.
    """

    def has_permission(self, request, view):
        return is_admin_user(request.user)


class IsAdminOrReadOnly(BasePermission):
    """
    Allows any authenticated user to perform read-only operations (GET, HEAD, OPTIONS).
    Write operations (POST, PATCH, DELETE) require the 'admin' role.
    """

    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False

        if request.method in SAFE_METHODS:
            return True

        return is_admin_user(request.user)


class IsAdminOrReadCreateOnly(BasePermission):
    """
    Allows any authenticated user to read and create (POST).
    Update/delete operations remain admin-only.
    """

    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False

        if request.method in SAFE_METHODS or request.method == "POST":
            return True

        return is_admin_user(request.user)


class IsOwnerOrAdmin(BasePermission):
    """
    Object-level permission:
    - Admin role can do anything.
    - Other authenticated users can only modify objects they own.

    Ownership is determined by checking for 'created_by' or 'uploaded_by'
    attributes on the object.
    """

    def has_permission(self, request, view):
        return bool(request.user and request.user.is_authenticated)

    def has_object_permission(self, request, view, obj):
        if is_admin_user(request.user):
            return True

        # Check common ownership fields
        if hasattr(obj, "created_by"):
            return obj.created_by == request.user
        if hasattr(obj, "uploaded_by"):
            return obj.uploaded_by == request.user

        return False
