"""
PREPOC ERP — RBAC Permission Classes
"""
from rest_framework.permissions import BasePermission, SAFE_METHODS


class IsOrganizationMember(BasePermission):
    """User must belong to the organization in context."""

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

    def has_object_permission(self, request, view, obj):
        if hasattr(obj, "organization_id"):
            return obj.organization_id == request.organization.id
        return True


class IsSuperAdmin(BasePermission):
    def has_permission(self, request, view):
        return request.user.is_authenticated and request.user.role == "SUPER_ADMIN"


class IsHRManager(BasePermission):
    def has_permission(self, request, view):
        return request.user.is_authenticated and request.user.role in (
            "SUPER_ADMIN", "HR_MANAGER",
        )


class IsTeamManager(BasePermission):
    def has_permission(self, request, view):
        return request.user.is_authenticated and request.user.role in (
            "SUPER_ADMIN", "HR_MANAGER", "TEAM_MANAGER",
        )


class IsAccountant(BasePermission):
    def has_permission(self, request, view):
        return request.user.is_authenticated and request.user.role in (
            "SUPER_ADMIN", "ACCOUNTANT",
        )


class IsEmployee(BasePermission):
    def has_permission(self, request, view):
        return request.user.is_authenticated


class IsAdminOrReadOnly(BasePermission):
    def has_permission(self, request, view):
        if request.method in SAFE_METHODS:
            return request.user.is_authenticated
        return request.user.is_authenticated and request.user.role == "SUPER_ADMIN"


class IsSelfOrAdmin(BasePermission):
    """Allow users to access their own records; admins access all."""

    def has_object_permission(self, request, view, obj):
        if request.user.role in ("SUPER_ADMIN", "HR_MANAGER"):
            return True
        user_field = getattr(obj, "user", None) or getattr(obj, "employee", None)
        if user_field is None:
            return False
        if hasattr(user_field, "user"):
            return user_field.user == request.user
        return user_field == request.user


class CanApprove(BasePermission):
    """User must be designated approver for the object."""

    def has_object_permission(self, request, view, obj):
        if request.user.role == "SUPER_ADMIN":
            return True
        return obj.approver == request.user


# -----------------------------------------------------------------------------
# NEW ENTERPRISE RBAC PERMISSION FACTORIES (PHASE 4)
# -----------------------------------------------------------------------------

def RequirePermission(permission_code: str):
    """
    Factory that generates a BasePermission class ensuring the user 
    has the specified RBAC permission (e.g., 'hr.employee.view').
    """
    class HasPerm(BasePermission):
        def has_permission(self, request, view):
            if not request.user or not request.user.is_authenticated:
                return False
                
            # 1. Feature Flag Check
            module = permission_code.split('.')[0].upper()
            from core.utils.feature_flags import is_feature_enabled
            if not is_feature_enabled(getattr(request, "organization", None), module):
                return False
                
            # 2. RBAC Check
            return permission_code in request.user.rbac_permissions
            
    # Name the class dynamically for easier debugging in tracebacks
    HasPerm.__name__ = f"RequirePermission_{permission_code.replace('.', '_')}"
    return HasPerm


def RequireAnyPermission(permission_codes: list[str]):
    """
    Factory that generates a BasePermission class ensuring the user 
    has AT LEAST ONE of the specified RBAC permissions.
    """
    class HasAnyPerm(BasePermission):
        def has_permission(self, request, view):
            if not request.user or not request.user.is_authenticated:
                return False
                
            from core.utils.feature_flags import is_feature_enabled
            org = getattr(request, "organization", None)
            user_perms = request.user.rbac_permissions
            
            for code in permission_codes:
                if code in user_perms:
                    module = code.split('.')[0].upper()
                    if is_feature_enabled(org, module):
                        return True
                        
            return False
            
    HasAnyPerm.__name__ = f"RequireAnyPermission"
    return HasAnyPerm
