from django.utils import timezone
from .models import ClientPermission

class PermissionChecker:
    """
    Verifica permisos de visualización para un usuario.
    
    Uso en views.py:
    ----------------
    from clients.permissions import PermissionChecker
    
    def dashboard_view(request):
        checker = PermissionChecker(request.user)
        
        # Filtrar equipos que puede ver
        allowed_teams = checker.get_allowed_teams()
        
        # Verificar permiso específico
        if checker.can_view_team(10, depth='historic'):
            # Mostrar métricas del team 10
        
        # Verificar partido
        if checker.can_view_match(123):
            # Mostrar datos del match 123
    """
    
    def __init__(self, user):
        self.user = user
        self._cache = {}  # Caché en memoria para el request actual
    
    # ============================================
    # MÉTODOS PÚBLICOS
    # ============================================
    
    def can_view_team(self, team_id, depth='instant'):
        """
        ¿Puede ver datos de este equipo?
        
        Args:
            team_id: ID del equipo (de internal DB)
            depth: 'instant' = solo partidos, 'historic' = incluye métricas históricas
        
        Returns:
            bool: True si puede ver, False si no
        """
        return self._check('team', team_id, depth)
    
    def can_view_match(self, match_id, depth='instant'):
        """¿Puede ver datos de este partido?"""
        return self._check('match', match_id, depth)
    
    def can_view_player(self, player_id, depth='instant'):
        """¿Puede ver datos de este jugador?"""
        return self._check('player', player_id, depth)
    
    def can_view_competition(self, competition_id, depth='instant'):
        """¿Puede ver datos de esta competición?"""
        return self._check('competition', competition_id, depth)
    
    def can_view_division(self, division_id, depth='instant'):
        """¿Puede ver datos de esta división?"""
        return self._check('division', division_id, depth)
    
    def can_view_region(self, region_id, depth='instant'):
        """¿Puede ver datos de esta región?"""
        return self._check('region', region_id, depth)
    
    def get_allowed_teams(self):
        """
        Retorna lista de IDs de equipos que el usuario puede ver.
        
        Returns:
            None: Si tiene acceso a todos los equipos (superuser)
            []: Si no tiene acceso a ningún equipo
            [10, 15, 20]: IDs de equipos permitidos
        """
        return self._get_allowed_resources('team')
    
    def get_allowed_matches(self):
        """Lista de IDs de partidos permitidos"""
        return self._get_allowed_resources('match')
    
    def get_allowed_players(self):
        """Lista de IDs de jugadores permitidos"""
        return self._get_allowed_resources('player')
    
    def get_allowed_competitions(self):
        """Lista de IDs de competiciones permitidas"""
        return self._get_allowed_resources('competition')
    
    # ============================================
    # LÓGICA INTERNA
    # ============================================
    
    def _check(self, level, resource_id, depth):
        """
        Verifica permiso con caché en memoria.
        
        Reglas:
        1. Superusuarios tienen acceso total
        2. Por defecto: BLOQUEADO (deny by default)
        3. Buscar permisos 'allow' activos
        4. Buscar permisos 'block' activos
        5. Block gana sobre allow (a igual prioridad)
        """
        
        # Bypass para superusuarios
        if self.user.is_superuser:
            return True
        
        # Verificar caché
        cache_key = f"{level}:{resource_id}:{depth}"
        if cache_key in self._cache:
            return self._cache[cache_key]
        
        # Calcular permiso
        result = self._evaluate(level, resource_id, depth)
        
        # Guardar en caché
        self._cache[cache_key] = result
        
        return result
    
    def _evaluate(self, level, resource_id, depth):
        """Evalúa permisos del usuario para un recurso específico"""
        
        now = timezone.now()
        # Usamos la clave en plural ahora
        key = f"{level}_ids" 
        
        # Obtener permisos activos para este level
        perms = ClientPermission.objects.filter(
            client=self.user,
            state='active',
            starts_at__lte=now,
            expires_at__gte=now,
            permission__is_active=True,
            permission__level=level
        ).select_related('permission').order_by('-permission__priority')
        
        # Filtrar: Buscamos permisos donde el resource_id esté en la lista del JSON
        # Nota: Hacemos esto en Python porque filtrar JSON arrays en DB varía según el motor (MySQL/Postgres)
        relevant = []
        for p in perms:
            ids_list = p.relation_id.get(key, [])
            if isinstance(ids_list, list) and resource_id in ids_list:
                relevant.append(p)
        
        if not relevant:
            return False  # No hay permisos → bloqueado por defecto
        
        # ...existing code (lógica de prioridades igual)...
        
        # Evaluar por prioridad
        has_allow = False
        has_block = False
        highest_priority = relevant[0].permission.priority
        
        for perm in relevant:
            if perm.permission.priority < highest_priority:
                break
            
            if depth == 'historic' and perm.permission.depth == 'instant':
                continue
            
            if perm.permission.type == 'allow':
                has_allow = True
            elif perm.permission.type == 'block':
                has_block = True
                break
        
        return has_allow and not has_block
    
    def _get_allowed_resources(self, level):
        """
        Retorna lista de IDs permitidos para un nivel.
        """
        
        if self.user.is_superuser:
            return None
        
        now = timezone.now()
        key = f"{level}_ids" # Clave en plural
        
        # Obtener allows
        allows = ClientPermission.objects.filter(
            client=self.user,
            state='active',
            starts_at__lte=now,
            expires_at__gte=now,
            permission__type='allow',
            permission__level=level,
            permission__is_active=True
        )
        
        allowed_ids = set()
        for p in allows:
            ids_list = p.relation_id.get(key, [])
            if isinstance(ids_list, list):
                allowed_ids.update(ids_list) # Agregamos todos los IDs de la lista
        
        # Obtener blocks
        blocks = ClientPermission.objects.filter(
            client=self.user,
            state='active',
            starts_at__lte=now,
            expires_at__gte=now,
            permission__type='block',
            permission__level=level,
            permission__is_active=True
        )
        
        blocked_ids = set()
        for p in blocks:
            ids_list = p.relation_id.get(key, [])
            if isinstance(ids_list, list):
                blocked_ids.update(ids_list)
        
        # Restar bloqueados de permitidos
        final = allowed_ids - blocked_ids
        
        return list(final) if final else []



# ============================================
# HELPERS PARA USAR EN TEMPLATES O VIEWS
# ============================================

def user_can_view_team(user, team_id, depth='instant'):
    """Helper rápido para usar en cualquier parte"""
    return PermissionChecker(user).can_view_team(team_id, depth)


def user_can_view_match(user, match_id, depth='instant'):
    """Helper rápido para verificar match"""
    return PermissionChecker(user).can_view_match(match_id, depth)


def get_user_teams(user):
    """Helper para obtener equipos permitidos"""
    return PermissionChecker(user).get_allowed_teams()