"""  
Кастомный backend аутентификации для связывания ролей с Django permissions API.

ВАЖНО: Этот backend НЕ использует таблицы Django permissions из public schema!
Он только эмулирует API has_perm(), читая роли из текущей tenant schema.
Это безопасно для мультитенантной архитектуры.

ВАЖНО: Backend проверяет текущую схему перед обращением к tenant-only таблицам.
В public схеме ролевые проверки пропускаются (fallback на стандартные Django permissions).

ВАЖНО: Этот backend НЕ наследуется от ModelBackend!
Он реализует только has_perm/has_module_perms для проверки прав на основе ролей.
Аутентификацию (authenticate/get_user) выполняют другие backends.
"""
from django.db import connection
from django_tenants.utils import get_public_schema_name
from user_roles.services import RoleService
from user_roles.models import Role


def _is_public_schema():
    """
    Проверяет, находимся ли мы в public схеме.
    В public схеме нет таблиц tenant-only моделей (UserRole, Role).
    """
    return connection.schema_name == get_public_schema_name()


def _is_tenant_user(user_obj):
    """
    Проверяет, является ли пользователь CustomUser (пользователь тенанта).
    PlatformAdmin не имеет ролей в тенантах.
    """
    from accounts.models import CustomUser
    return isinstance(user_obj, CustomUser)


class RoleBasedPermissionBackend:
    """
    Backend, который предоставляет права на основе роли пользователя в текущем тенанте.

    НЕ наследуется от ModelBackend! Реализует только проверку прав (has_perm/has_module_perms).
    Аутентификацию (authenticate/get_user) выполняют TenantUserBackend и PlatformAdminBackend.

    Как это работает:
    1. Django вызывает user.has_perm('products.add_product')
    2. Backend проверяет роль пользователя в ТЕКУЩЕЙ tenant schema (через RoleService)
    3. На основе роли возвращает True/False
    4. Никакие данные из public schema не используются!
    """

    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        Этот backend НЕ выполняет аутентификацию.
        Возвращает None, чтобы Django перешёл к следующему backend.
        """
        return None

    # Маппинг ролей на наборы разрешений
    # Формат: 'app_label': ['action1', 'action2', ...]
    # где action - это префикс permission: add_product -> add, change_order -> change
    ROLE_PERMISSIONS = {
        Role.OWNER: {
            # Владелец: полный доступ ко всем модулям
            'products': ['add', 'change', 'delete', 'view'],
            'inventory': ['add', 'change', 'delete', 'view'],
            'orders': ['add', 'change', 'delete', 'view'],
            'clients': ['add', 'change', 'delete', 'view'],
            'suppliers': ['add', 'change', 'delete', 'view'],
            'user_roles': ['add', 'change', 'delete', 'view'],
            'payments': ['add', 'change', 'delete', 'view'],
        },
        Role.MANAGER: {
            # Менеджер: доступ к основным операционным модулям (без настроек)
            'products': ['add', 'change', 'delete', 'view'],
            'inventory': ['add', 'change', 'delete', 'view'],
            'orders': ['add', 'change', 'delete', 'view'],
            'clients': ['add', 'change', 'delete', 'view'],
            'suppliers': ['add', 'change', 'view'],  # только просмотр и изменение, без удаления
            'payments': ['view'],
        },
        Role.FLORIST: {
            # Флорист: работа с заказами и просмотр товаров
            'products': ['view'],
            'inventory': ['view', 'change'],  # может обновлять остатки при сборке заказов
            'orders': ['change', 'view'],
        },
        Role.COURIER: {
            # Курьер: только просмотр и обновление статуса заказов
            'orders': ['change', 'view'],
        },
    }

    def has_perm(self, user_obj, perm, obj=None):
        """
        Проверяет, имеет ли пользователь указанное разрешение.

        Формат разрешения: 'app_label.action_modelname'
        Например: 'products.add_product', 'orders.change_order'

        Args:
            user_obj: Пользователь
            perm: Строка разрешения в формате 'app.action_model'
            obj: Опциональный объект для object-level permissions

        Returns:
            bool: True если пользователь имеет разрешение
        """
        # Если пользователь не аутентифицирован, нет доступа
        if not user_obj.is_authenticated:
            return False

        # Определяем тип пользователя
        is_tenant = _is_tenant_user(user_obj)

        # Для CustomUser (пользователи тенантов) НЕ вызываем super().has_perm()
        # т.к. AUTH_USER_MODEL = PlatformAdmin, и ModelBackend будет пытаться
        # искать permissions в Django Permission таблице для PlatformAdmin
        if is_tenant:
            # Суперпользователь имеет все права
            if user_obj.is_superuser:
                return True

            # ВАЖНО: В public схеме нет таблиц UserRole/Role!
            if _is_public_schema():
                return False

            # Для CustomUser получаем роль пользователя в текущем тенанте
            user_role = RoleService.get_user_role(user_obj)
            if not user_role:
                return False

            # Парсим разрешение: 'app_label.action_modelname'
            try:
                app_label, codename = perm.split('.')
                action = codename.split('_')[0]
            except (ValueError, IndexError):
                return False

            # Проверяем, есть ли у роли это разрешение
            role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
            app_perms = role_perms.get(app_label, [])

            return action in app_perms
        else:
            # Для PlatformAdmin - этот backend НЕ обрабатывает PlatformAdmin
            # Возвращаем None, чтобы Django перешёл к другому backend
            # (PlatformAdminBackend должен обработать это)
            return None

    def has_module_perms(self, user_obj, app_label):
        """
        Проверяет, имеет ли пользователь какие-либо разрешения для приложения.

        Используется в Django admin для определения, показывать ли модуль в навигации.

        Args:
            user_obj: Пользователь
            app_label: Название приложения (например, 'products', 'orders')

        Returns:
            bool: True если пользователь имеет хотя бы одно разрешение для приложения
        """
        # Если пользователь не аутентифицирован, нет доступа
        if not user_obj.is_authenticated:
            return False

        # Определяем тип пользователя
        is_tenant = _is_tenant_user(user_obj)

        # Для CustomUser (пользователи тенантов) НЕ вызываем super().has_module_perms()
        if is_tenant:
            # Суперпользователь имеет все права
            if user_obj.is_superuser:
                return True

            # ВАЖНО: В public схеме нет таблиц UserRole/Role!
            if _is_public_schema():
                return False

            # Для CustomUser получаем роль пользователя в текущем тенанте
            user_role = RoleService.get_user_role(user_obj)
            if not user_role:
                return False

            # Проверяем, есть ли у роли какие-либо разрешения для этого приложения
            role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
            return app_label in role_perms and len(role_perms[app_label]) > 0
        else:
            # Для PlatformAdmin - этот backend НЕ обрабатывает PlatformAdmin
            # Возвращаем None, чтобы Django перешёл к другому backend
            return None
