"""Permission enforcement helpers for Loyalty APIs."""
from __future__ import annotations

from collections.abc import Callable

from fastapi import Depends

from app.core.config import settings
from app.core.security import get_current_user
from shared.exceptions import ForbiddenError
from shared.security import CurrentUser

_ADMIN_ROLES = frozenset(
    {"platform_admin", "tenant_owner", "tenant_admin"}
)


def user_has_permission(user: CurrentUser, permission: str) -> bool:
    if any(role in _ADMIN_ROLES for role in user.roles):
        return True
    roles = set(user.roles)
    if "loyalty.manage" in roles or permission in roles:
        return True
    # Platform-wide loyalty.view grants any *.view leaf.
    if "loyalty.view" in roles and permission.endswith(".view"):
        return True
    # Resource manage (e.g. loyalty.programs.manage) grants that tree.
    parts = permission.split(".")
    if len(parts) >= 3:
        manage = f"{parts[0]}.{parts[1]}.manage"
        if manage in roles:
            return True
    return False


def require_permissions(*permissions: str) -> Callable:
    """Deny unless AUTH is off, user is admin, or any listed permission is present."""

    async def _dependency(
        user: CurrentUser = Depends(get_current_user),
    ) -> CurrentUser:
        if not settings.auth_required:
            return user
        if any(user_has_permission(user, perm) for perm in permissions):
            return user
        raise ForbiddenError(
            "دسترسی مجاز نیست",
            error_code="permission_denied",
            details={"required": list(permissions)},
        )

    return _dependency
