from django.conf import settings
from rest_framework.permissions import BasePermission, DjangoModelPermissions


class DjangoModelPermissionsWithView(DjangoModelPermissions):
    """Enforce model-level permissions for all requests including read/GET requests."""
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }



class IsInternalRequest(BasePermission):
    """Allow only callers presenting the internal shared secret (MCP agent flow)."""

    message = "Internal access only."

    def has_permission(self, request, view):
        return request.headers.get("X-Internal-Secret") == settings.INTERNAL_API_SECRET


class IsAdmin(BasePermission):
    def has_permission(self, request, view):
        return bool(
            request.user
            and request.user.is_authenticated
            and request.user.role == "ADMIN"
        )


class CanManageRoles(BasePermission):
    """Permission-driven access to Role / Group & Permissions management.

    ADMIN (and superusers) always have access. Non-admins need the matching
    Django auth.Group model permission — granted the same way as any other
    dynamic permission, by adding it to a group they belong to. This mirrors
    DjangoModelPermissionsWithView but works on plain APIViews (RoleListView,
    RolePermissionsView, etc.) that have no queryset/model to introspect.

    Note: the ADMIN role/group itself can never be edited, deleted, or cloned
    regardless of this permission (enforced separately in the views via
    is_admin_role checks), so holding these permissions cannot be used to
    grant oneself ADMIN access."""

    perms_map = {
        'GET': 'auth.view_group',
        'POST': 'auth.add_group',
        'PUT': 'auth.change_group',
        'PATCH': 'auth.change_group',
        'DELETE': 'auth.delete_group',
    }

    def has_permission(self, request, view):
        user = request.user
        if not (user and user.is_authenticated):
            return False
        if user.role == "ADMIN" or user.is_superuser:
            return True
        required = self.perms_map.get(request.method)
        return bool(required) and user.has_perm(required)



